1.学习视频:JDBC封装(4)—>直播
2.学习内容*
1>封装JDBC的目的:
1.减少代码的冗余(ORM框架)
2.增强底层执行的性能(连接池)
2>复习注解
1.注解写法
@XXXX (信息)
2.注解放置在哪里写
类 方法 属性 构造 变量 参数(前面)
3.Java中定义好的注解
@Deprecated 废弃的
@Override 检测方法是否是重写
@SuppressWarnings 去掉程序中的警告(尽量不要用 尽量通过编写代码去掉警告)
4.如何自己定义注解
描述一个自己的类 @interface
类的上面通过元注解来描述
@Target
@Retention
@Inherited
想要携带一些信息 自定义注解类型 添加方法
方法要求必须有返回值 返回值类型:
基本 String 枚举 注解 数组
方法的作用:将我们传递的信息 搬走了 交给别人
5.注解的作用
充当注释 仅仅是一个文字说明
代码检测 @Override
携带信息
6.如何访问到注解对象 @XXX—>定义
如何获取里面的信息(需要反射机制)
反射读取注解内的SQL
3>代理模式<br />为其他对象提供一个代理以控制对某个对象的访问。代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。<br />其实就是代理类为被代理类预处理消息、过滤消息并在此之后将消息转发给被代理类,之后还能进行消息的后置处理。代理类和被代理类通常会存在关联关系(即上面提到的持有的被带离对象的引用),代理类本身不实现服务,而是通过调用被代理类中的方法来提供服务。<br />静态代理<br />创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时使其也实现这个接口。在代理类中持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。<br />动态代理<br />利用反射机制在运行时创建代理类。<br />动态代理具体步骤:1. 通过实现 InvocationHandler 接口创建自己的调用处理器;1. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;1. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;1. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
链接:https://www.jianshu.com/p/9bcac608c714—>详解代理模式(来自简书)
3.练习的代码—>查询单条已及多条sql语句(任何表格都可)—其中含有反射
//设计一个方法 将rs结果集的值取出 存入一个新的容器中Object handleResult(ResultSet rs, Class resultType) throws SQLException {Object result = null;if(resultType==int.class || resultType==Integer.class){result = rs.getInt(1);}else if(resultType==float.class || resultType==Float.class){result = rs.getFloat(1);}else if(resultType==String.class){result = rs.getString(1);}else{// map domainif(resultType== Map.class){ //mapresult = this.getMap(rs);}else{ //domainresult = this.getObject(rs,resultType);}}return result;}//设计一个方法 负责帮助handleResult方法拼接 map类型//只需要提供给handleResult一个方法使用 private就够了private Map getMap(ResultSet rs) throws SQLException {//创建一个Map对象-->用来存放列名和其对应值Map result = new HashMap<String,Object>();//将结果集的信息取出ResultSetMetaData rsmd = rs.getMetaData();//对该信息进行遍历for(int i=1;i<=rsmd.getColumnCount();i++){//结果集的列从1开数的,循环是小于等于列名//获取结果集中查询到的列名String columnName = rsmd.getColumnName(i);//通过列名获取 列值Object value = rs.getObject(columnName);//存入map集合中result.put(columnName,value);}return result;}//设计另一个方法 负责帮助handleResult方法拼接对象private Object getObject(ResultSet rs,Class resultType) throws SQLException {Object obj = null;//存储最后的值try {//通过反射创建一个domain类型的对象obj = resultType.newInstance();//调用了一个默认无参数的构造方法创建了一个对象 new Bank//通过rs取值 存入obj中ResultSetMetaData rsmd = rs.getMetaData();for(int i=1;i<=rsmd.getColumnCount();i++){//遍历结果集//获取结果集中的每一个列名String columnName = rsmd.getColumnName(i);//获取对应列名的值 写列名或者i都可以Object value = rs.getObject(columnName);//根据columnName反射找到obj中的某一个属性 操作属性将value存入//Field field = resultType.getDeclaredField(columnName);Field field = obj.getClass().getDeclaredField(columnName);//修改属性权限field.setAccessible(true);//其实应该找寻属性对应的set方法 invoke那个set方法//直接操作私有属性 取值field.set(obj,value);//操作属性 给属性赋值//Atm atm = new Atm(); Atm atm = clazz.newInstance();// Field field = clazz.getField(); filed--->aname//atm.setAname("zzt"); field.set(atm,"zzt");}} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (NoSuchFieldException e) {e.printStackTrace();}return obj;}
public <T>T selectList(String sql,Object obj,Class resultType){try {//0.创建一个用来存储最终返回值的变量ArrayList<T> List = new ArrayList<T>();//1.解析SQL//keyList{aname,apassword,abalance} 按照解析顺序存储的key//newSQL--->还原成原来那种带有问号的形式--->pstat对象才认识SQLAndKey sqlAndKey = handler.parseSQL(sql);//2.加载驱动Class.forName(className);//3.获取连接Connection conn = DriverManager.getConnection(url, user, password);//4.状态参数(newSQL)PreparedStatement pstat = conn.prepareStatement(sqlAndKey.getSQL());//调用sqlAndKey获取没有标识符含 ? 的sql语句//5.将SQL和值拼接在一起if(obj!=null){handler.handleParameter(pstat,obj,sqlAndKey.getKeyList());}/** 如果1个值 直接拿来用* 设计一个方法 好多类型判断* 如果n个值 遍历keyList* 每一次循环拿到一个key* 根据key去容器(map,domain)中获取值* pstat.setObject(位置,值)*///6.执行ResultSet rs = pstat.executeQuery();while(rs.next()){//7.将结果集中的数据取出---存入一个新的容器类List.add((T)handler.handleResult(rs,resultType));}//8.关闭rs.close();pstat.close();conn.close();} catch (Exception e) {e.printStackTrace();}//返回最终对象return List;}//重载hhh 如果obj==null,可以直接调这个方法啦public <T> List<T> selectList(String sql,Class resultType){return this.selectList(sql,null,resultType);}//设计一个方法 可以查询任何一个表格单条语句public <T> T selectOne(String sql,Object obj,Class resultType){return (T)this.selectList(sql,obj,resultType).get(0);}
//查询多条方法public List<Bank> selectAll(){String sql = "select * from bs";return sqlSession.selectList(sql,null,Bank.class);}//查询单条public Bank selectOne1(String bname){String sql = "select * from bs where bname = #{bname}";return sqlSession.selectOne(sql,bname,Bank.class);}public static void main(String[] args) {BankDao dao = new BankDao();//List<Bank> list = dao.selectAll();Bank bank = dao.selectOne1("小小");System.out.println(bank);}
总结:
这次的直播讲解了查询SQL语句的方法,这种方法可以查询单条或者多条语句,该方法用到了反射机制,跟昨天讲解的增删改方法有相似之处,昨天的听懂了,所以今天的理解也比较容易。
不足之处:
在反射方面,没有很好的掌握,在老师提到时,不能很快想到,对其中的方法用法学习也只是在皮毛上……
