ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ORM框架封装(六)之连接池

2021-02-06 13:58:26  阅读:143  来源: 互联网

标签:java 封装 String rs pstat ORM sql import 连接池


  • pool
package pool;

import java.util.ArrayList;
import java.util.List;

/**
 * 这是自己设计的一个管理类
 * 好多连接需要存储---连接池---List
 * 目的是为了管理连接
 */
public class ConnectionPool {

    //属性--所谓的"大池子"
    private List<MyConnection> connectionList = new ArrayList();

    //块 目的是在当前类创建对象的时候 给连接池集合赋值
    {
        int count = 5;
        for(int i=1;i<=count;i++){
            connectionList.add(new MyConnection());
        }
    }

    //需要给用户提供一个方法
    //可以去"大池子"里获取一个可用连接
    //参数 不用
    //返回值--连接 Conn  MyConn
    //考虑用户使用完以后---> MyConn状态  切换状态即可
    public MyConnection getMC(){
        MyConnection result = null;
        //去连接池集合中寻找
        for(int i=0;i<connectionList.size();i++){
            MyConnection mc = connectionList.get(i);
            //判断mc的状态
            if(mc.isUsed() == false){//mc是空闲的  可用
                mc.setUsed(true);//找到一个mc是可用的 马上占有
                result = mc;
                break;
            }
        }
        return result;
    }

}

package pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 这个类就是我们自己要封装的那个类
 * 目的是为了将一个连接和一个状态放在一起的
 */
public class MyConnection {

    private static String className = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
    private static String username = "root";
    private static String password = "123456";

    //类的加载顺序???
    //  属性
    //  方法
    //  块
    //  构造
    //  内存中开辟堆内存对象空间 往空间内摆放信息

    //  块自动调用执行

    //两个属性
    private Connection conn;
    private boolean used = false;//true被占用 false空闲的

    static{
        try {
            Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    {
        //目的是为了每次构造方法执行之前
        //默认先执行这个代码块---为了给conn属性赋值
        try {
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void setUsed(boolean used) {
        this.used = used;
    }

    //补充两个get方法
    public Connection getConn() {
        return conn;
    }
    public boolean isUsed() {//boolean的get方法命名规范是以is开头
        return used;
    }
}

package pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

@SuppressWarnings("all")
public class TestConnection {

    public static void main(String[] args) throws Exception {
//        String className = "com.mysql.jdbc.Driver";
//        String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
//        String username = "root";
//        String password = "123456";
//        String sql = "select sid,sname,ssex,sage from student";
//
//        long t1 = System.currentTimeMillis();
//        //JDBC
//        //1.导包
//        //2.加载驱动
//        Class.forName(className);
//        //3.获取连接
//        Connection conn = DriverManager.getConnection(url,username,password);
//        long t2 = System.currentTimeMillis();
//        //4.获取状态参数
//        PreparedStatement pstat = conn.prepareStatement(sql);
//        //5.执行操作  增删改 查询--结果
//        ResultSet rs = pstat.executeQuery();
//        while(rs.next()){
//            int sid = rs.getInt("sid");
//            String sname = rs.getString("sname");
//            String ssex = rs.getString("ssex");
//            int sage = rs.getInt("sage");
//            System.out.println(sid+"--"+sname+"--"+ssex+"--"+sage);
//        }
//        //6.关闭操作
//        rs.close();
//        pstat.close();
//        //conn.close();
//        long t3 = System.currentTimeMillis();
//        System.out.println("创建连接所需时间:"+(t2-t1));
//        System.out.println("执行操作所需时间:"+(t3-t2));


        long t1 = System.currentTimeMillis();
        //1.导包
        //2.加载驱动??------>加载连接池对象
        ConnectionPool pool = new ConnectionPool();
        //3.获取连接??------>连接池对象获取
        MyConnection mc = pool.getMC();
        Connection conn = mc.getConn();
        long t2 = System.currentTimeMillis();
        //4.状态参数
        PreparedStatement pstat = conn.prepareStatement("select * from student");
        //5.执行操作
        ResultSet rs = pstat.executeQuery();
        //6.关闭
        rs.close();
        pstat.close();
        mc.setUsed(false);//释放连接---修改状态
        System.out.println(t2-t1);
        //=====================================================
        long t3 = System.currentTimeMillis();
        //1.导包
        //2.加载驱动??------>加载连接池对象
        //3.获取连接??------>连接池对象获取
        MyConnection mc2 = pool.getMC();
        Connection conn2 = mc2.getConn();
        long t4 = System.currentTimeMillis();
        //4.状态参数
        PreparedStatement pstat2 = conn2.prepareStatement("select * from student");
        //5.执行操作
        ResultSet rs2 = pstat2.executeQuery();
        //6.关闭
        rs2.close();
        pstat2.close();
        mc2.setUsed(false);//释放连接---修改状态
        System.out.println(t4-t3);
    }


}

  • annotation
package orm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Insert {

    //理解为注解就是一个搬运工
    //帮用户搬运一条SQL语句  给别人(框架)去解析
    //设计一个方法  没有参数 有返回值
    String value();

}
package orm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Delete {

    //理解为注解就是一个搬运工
    //帮用户搬运一条SQL语句  给别人(框架)去解析
    //设计一个方法  没有参数 有返回值
    String value();

}

package orm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Update {

    //理解为注解就是一个搬运工
    //帮用户搬运一条SQL语句  给别人(框架)去解析
    //设计一个方法  没有参数 有返回值
    String value();

}

package orm.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Select {

    //理解为注解就是一个搬运工
    //帮用户搬运一条SQL语句  给别人(框架)去解析
    //设计一个方法  没有参数 有返回值
    String value();

}

package orm;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Handler {

    //============================
    //设计一个小弟方法---帮助我们解析SQL语句
    SQLAndKey parseSQL(String sql){
        //解析之前肯定需要两个变量
        StringBuilder newSQL = new StringBuilder();
        List<String> keyList = new ArrayList<>();
        //解析SQL
        //insert into student values(#{sid},#{sname},#{ssex},#{sage})
        while(true){
            //按照规定的结构来找寻索引位置
            int left = sql.indexOf("#{");
            int right = sql.indexOf("}");
            //判断两个索引的位置是否合法
            if(left!=-1 && right!=-1 && left<right){
                //找到一组#{key}
                newSQL.append(sql.substring(0,left));//截取左边的部分拼接到newSQL里
                newSQL.append("?");
                keyList.add(sql.substring(left+2,right));
            }else{//找不到
                newSQL.append(sql);
                break;
            }
            sql = sql.substring(right+1);
        }
        return new SQLAndKey(newSQL,keyList);
    }
    //----------------------------
    //设计一个小小弟--负责帮下面那个handlerParameter方法处理map集合的拼接
    private void setMap(PreparedStatement pstat, Object obj, List<String> keyList) throws SQLException {
        //按照keyList规定的顺序 从map中获取元素 让pstat拼接到SQL上
        //还原一下obj类型
        Map map = (Map)obj;
        for(int i=0;i<keyList.size();i++){
            pstat.setObject(i+1,map.get(keyList.get(i)));
        }
    }
    //设计一个小小弟--负责帮下面那个handlerParameter方法处理domain的拼接
    private void setDomain(PreparedStatement pstat,Object obj,List<String> keyList) throws SQLException, NoSuchFieldException, IllegalAccessException {
        //获取obj类型
        Class clazz = obj.getClass();
        //遍历keyList 规定了顺序
        for(int i=0;i<keyList.size();i++){
            String key = keyList.get(i);
            //去domain对象中获取key对应属性的值
            Field field = clazz.getDeclaredField(key);
            //直接操作私有属性啦
            field.setAccessible(true);
            //拼接
            //  Object obj = 对象;        field = clazz.getField();
            //  value = obj.getName();   value = field.get(对象);
            pstat.setObject(i+1,field.get(obj));
        }
    }
    //设计一个小弟方法---帮我们处理参数(SQL和对象中的值拼接在一起)
    //  参数pstat  Object  顺序? keyList<key>
    void handlerParameter(PreparedStatement pstat,Object obj,List<String> keyList) throws SQLException {
        //获取这个obj对象的Class
        Class clazz = obj.getClass();
        //clazz通常可以是什么类型
        //  1.基础类型  int-Integer  float-Float  String
        //  2.domain类型  Student  Atm  Teacher
        //  3.map类型
        if(clazz==int.class || clazz==Integer.class){
            pstat.setInt(1,(Integer)obj);
        }else if(clazz==float.class || clazz==Float.class){
            pstat.setFloat(1,(Float)obj);
        }else if(clazz==double.class || clazz==Double.class){
            pstat.setDouble(1,(Double)obj);
        }else if(clazz==String.class){
            pstat.setString(1,(String)obj);
        }else if(clazz.isArray()){
            //自己处理 数组循环  对不起我不支持
        }else{
            //认为只剩下两个可能
            //1.map
            if(obj instanceof Map){
                this.setMap(pstat,obj,keyList);
            }else{//domain
                try {
                    this.setDomain(pstat,obj,keyList);
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //----------------------------
    //设计一个小小弟--负责帮下面那个handlerResult方法处理map返回值
    private Map getMap(ResultSet rs) throws SQLException {
        //创建map
        Map result = new HashMap<String,Object>();
        //获取rs中的全部信息(表格原来的列名 和 查询到的值)  Set<Map<列名,值>>
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        //遍历含有列的信息
        for(int i=1;i<=resultSetMetaData.getColumnCount();i++){
            //获取一个列名字
            String columnName = resultSetMetaData.getColumnName(i);
            //根据列名字获取rs中的值
            Object value = rs.getObject(columnName);
            result.put(columnName,value);
        }
        return result;
    }
    //设计一个小小弟--负责帮下面那个handlerResult方法处理domain返回值
    private Object getDomain(ResultSet rs,Class resultType) throws IllegalAccessException, InstantiationException, SQLException, NoSuchFieldException {
        Object obj = null;
        //通过Class反射创建对象
        obj = resultType.newInstance();
        //遍历rs
        ResultSetMetaData resultSetMetaData = rs.getMetaData();
        for(int i=1;i<=resultSetMetaData.getColumnCount();i++){
            //获取一个列名字
            String columnName = resultSetMetaData.getColumnName(i);
            //反射找domain对象中对应列名的哪个属性
            Field field =resultType.getDeclaredField(columnName);
            //操作私有属性
            field.setAccessible(true);
            field.set(obj,rs.getObject(columnName));
        }
        return obj;
    }
    //设计一个小弟方法---帮我们处理返回值(rs信息取出 组装成一个对象 基础类型 domain map)
    Object handlerResult(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==double.class || resultType==Double.class){
            result = rs.getDouble(1);
        }else if(resultType==String.class){
            result = rs.getString(1);
        }else{
            //在这认为是对象  map  domain
            if(resultType==Map.class){
                result = this.getMap(rs);
            }else{
                try {
                    result = this.getDomain(rs,resultType);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }
    //============================
}

package orm;

import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 这是自己定义的一个规则
 * 提供策略的规则接口
 */
public interface RowMapper {

    //设计一个规则方法
    //将rs的信息组装成一个对象domain
    //是否需要参数  rs
    //是否需要返回值  <T>
    <T>T mapperRow(ResultSet rs) throws SQLException;

}

package orm;

import java.util.ArrayList;
import java.util.List;

/**
 * 这是我们自己定义的类
 * 是为了解析带有#{key}形式的SQL时候
 * 装载解析后的返回值的
 * 解析后的返回值有两个
 * 一个是带有问号形式的原来SQL
 * 一个是ArrayList集合 集合内存放好多key
 */
public class SQLAndKey {

    //属性 存放原先形式的sql 带问号的
    private StringBuilder sql = new StringBuilder();
    //属性 存放解析出来的那些#{key}
    private List<String> keyList = new ArrayList();

    //带参数的构造方法
    public SQLAndKey(StringBuilder sql,List<String> keyList){
        this.sql = sql;
        this.keyList = keyList;
    }

    public String getSQL(){
        return this.sql.toString();
    }
    public List<String> getKeyList(){
        return this.keyList;
    }

}

package orm;

import orm.annotation.Delete;
import orm.annotation.Insert;
import orm.annotation.Select;
import orm.annotation.Update;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 单独设计了一个类
 * 负责帮所有的DAO来做事
 * 以后只能在这个类的方法中见到JDBC的流程啦
 * 以后所有的DAO再也看不见JDBC啦
 * 以后的DAO只保留了一条SQL语句
 */
@SuppressWarnings("all")
public class SqlSession {

    private Handler handler = new Handler();

    //面向配置文件开发
    //驱动类 账号 密码都存在文件中

    //单独设计一个小弟方法
    //负责处理所有的增删改操作
    //  参数  SQL , SQL语句上需要的那些问号值
    //  返回值?  void   int--->行数       原本对象形式的容器--->数组Object[] 集合
    //  insert into student values(?,?,?,?)
    //  values->Object[] {10,"zzt","男",18}
    public void update(String sql,Object... values){//容器目的存储好几个问号值的
        String className = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        try {
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sql);
            //给SQL问号赋值的过程
            //  赋值 几个 什么类型
            for(int i=0;i<values.length;i++){
                pstat.setObject(i+1,values[i]);
            }
            //执行操作啦
            pstat.executeUpdate();
            //关闭
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void insert(String sql,Object... values){
        this.update(sql,values);
    }
    public void delete(String sql,Object... values){
        this.update(sql,values);
    }
    //单独设计一个小弟方法
    //负责处理所有DAO的单条查询
    //  参数      SQL  Object[]
    //  返回值    <T> Object(Student Atm)
    public <T>T selectOne(String sql,RowMapper rm,Object... values){
        Object obj = null;
        String className = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        try {
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sql);
            //给SQL问号赋值的过程
            //  赋值 几个 什么类型
            for(int i=0;i<values.length;i++){
                pstat.setObject(i+1,values[i]);
            }
            //-------------------------------------------
            //执行操作啦---查询
            ResultSet rs = pstat.executeQuery();
            if(rs.next()){
                //将rs中的数据取出来  存入一个新的容器里  domain 数组 集合
                //1.  rs数据取出来 存入一个新的容器--->domain  map
                //2.  策略模式----多态的时候  银行取钱  去银行取钱的流程固定  每一人执行结果不一样
                //              一个类负责制定流程(方法)  提供一个参数(接口)  真正传参数的时候具体子类
                //              public void test(接口 a){
                //                  1.
                //                  2.
                //                  3.不一样 a.方法();
                //                  4.
                //                  5.
                //              }
                //              Test t = new Test();
                //              t.test(a子类对象);  子类重写之后的效果
                //  将rs的信息拿出来  组装成一个对象
                obj = rm.mapperRow(rs);
                //3.  利用反射来完成
            }
            //关闭
            rs.close();//rs就可以关闭啦
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T)obj;
    }

    //设计一个小弟方法
    //负责处理所有DAO的多条查询
    //  参数
    //  返回值
    //  select * from student where ssex = ? and sage = ?
    //  values  男  18
    //  三行记录
    public <T> List<T> selectList(String sql, RowMapper rm, Object...values){
        List<T> list = new ArrayList();
        String className = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        try {
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sql);
            //给SQL问号赋值的过程
            //  赋值 几个 什么类型
            for(int i=0;i<values.length;i++){
                pstat.setObject(i+1,values[i]);
            }
            //-------------------------------------------
            //执行操作啦---查询
            ResultSet rs = pstat.executeQuery();
            while(rs.next()){
                //将rs中的数据取出来  存入一个新的容器里  domain 数组 集合
                //1.  rs数据取出来 存入一个新的容器--->domain  map
                //2.  策略模式----多态的时候  银行取钱  去银行取钱的流程固定  每一人执行结果不一样
                //              一个类负责制定流程(方法)  提供一个参数(接口)  真正传参数的时候具体子类
                //              public void test(接口 a){
                //                  1.
                //                  2.
                //                  3.不一样 a.方法();
                //                  4.
                //                  5.
                //              }
                //              Test t = new Test();
                //              t.test(a子类对象);  子类重写之后的效果
                //  将rs的信息拿出来  组装成一个对象
                T obj = (T)rm.mapperRow(rs);
                list.add(obj);
                //3.  利用反射来完成
            }
            //关闭
            rs.close();//rs就可以关闭啦
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


    //方案二(利用反射将上述的方法参数values处理一下)
    public void update(String sql,Object obj){
        //Object obj可以理解为是原来的那个domain
        //新增
        //insert into student values(#{sid},#{sname},#{ssex},#{sage})
        //values[]  sid sname ssex sage  按顺序的?
        //student对象  sid sname ssex sage属性---->属性值拼到对应的问号位置上?
        //如果用户是按照上面的SQL写过来的
        //我们需要做什么???
        // 1.解析SQL---> 要每一个#{key}  将#{key}替换回原来的?
        //      一条原来形式的sql语句     String sql
        //      一堆key  集合ArrayList  ArrayList<String>       对象
        SQLAndKey sqlAndKey = handler.parseSQL(sql);
        //执行JDBC的流程
        String className = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
        String username = "root";
        String password = "123456";
        try {
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sqlAndKey.getSQL());
            //给SQL问号赋值的过程
            //  赋值 几个 什么类型
            //  问号的值存储在一个对象里的obj  对象里面的值和SQL拼接在一起
            if(obj!=null) {
                handler.handlerParameter(pstat, obj, sqlAndKey.getKeyList());
            }
            //执行操作啦
            pstat.executeUpdate();
            //关闭
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public void insert(String sql,Object obj){this.update(sql,obj);}
    public void delete(String sql,Object obj){this.update(sql,obj);}
    //方案二(利用反射将selectOne方法处理一下  rm  values)
    public <T>T selectOne(String sql,Object obj,Class resultType){
        Object result = null;
        try {
            //1.解析sql--带#{key}
            SQLAndKey sqlAndKey = handler.parseSQL(sql);
            //2.获取连接
            String className = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
            String username = "root";
            String password = "123456";
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sqlAndKey.getSQL());
            //拼接SQL和问号的值
            if(obj!=null) {
                handler.handlerParameter(pstat, obj, sqlAndKey.getKeyList());
            }
            //-------------------------------------------
            //执行操作啦---查询
            ResultSet rs = pstat.executeQuery();
            if(rs.next()){
                //组装对象 将rs里面的信息取出来 组装成一个对象
                result = handler.handlerResult(rs,resultType);
            }
            //关闭
            rs.close();//rs就可以关闭啦
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T)result;
    }
    public <T>List<T> selectList(String sql,Object obj,Class resultType){
        List<T> list = new ArrayList();
        try {
            //1.解析sql--带#{key}
            SQLAndKey sqlAndKey = handler.parseSQL(sql);
            //2.获取连接
            String className = "com.mysql.jdbc.Driver";
            String url = "jdbc:mysql://localhost:3306/newtest?useSSL=false&characterEncoding=utf8";
            String username = "root";
            String password = "123456";
            //加载驱动
            Class.forName(className);
            //获取连接
            Connection conn = DriverManager.getConnection(url,username,password);
            //创建状态参数----预处理
            PreparedStatement pstat = conn.prepareStatement(sqlAndKey.getSQL());
            //拼接SQL和问号的值
            if(obj!=null) {
                handler.handlerParameter(pstat, obj, sqlAndKey.getKeyList());
            }
            //-------------------------------------------
            //执行操作啦---查询
            ResultSet rs = pstat.executeQuery();
            while(rs.next()){
                //组装对象 将rs里面的信息取出来 组装成一个对象
                list.add((T)handler.handlerResult(rs,resultType));
            }
            //关闭
            rs.close();//rs就可以关闭啦
            pstat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    //=======================================================================

    //设计一个方法  让SqlSession帮DAO创建一个代理对象
    //让代理对象去代替DAO做一件事情(告知SqlSession做事--调用方法那一行代码的过程)

    //如果想要使用代理对象来帮忙做事
    //前提是  被代理的那个对象必须是一个接口
    public <T>T getMapper(Class clazz){//clazz---StudentDao(接口) 代理对象DAO的子类对象
        return (T)Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //invoke方法是代理对象该具体做的事情
                //帮助原来的DAO做他原本该做的事情
                //DAO原本只做了一件事  调用sqlSession.方法();
                //invoke方法方式代理对象的方法
                //  proxy代理对象
                //  method被代理的那个方法(DAO的方法)
                //  args被代理方法执行时的那个参数

                //调用上述四个方法的其中一个  增删改查  哪一个呢? 注解名字
                //1.获取方法上面的注解
                Annotation an = method.getAnnotations()[0];
                //2.获取这个注解的类型
                Class type = an.annotationType();//Insert Delete Update Select
                //3.想要调用如下的方法,还需要注解对象里面的那条SQL语句
                //通过注解类型 获取注解类中的那个value方法
                Method valueMethod = type.getDeclaredMethod("value");
                //反射执行这个方法 获取结果-->SQL
                String sql = (String)valueMethod.invoke(an);
                //最好将args做一个严谨的处理
                Object param = args==null ? null : args[0];
                if(type == Insert.class){
                    SqlSession.this.insert(sql,param);
                }else if(type == Delete.class){
                    SqlSession.this.delete(sql,param);
                }else if(type == Update.class){
                    SqlSession.this.update(sql,param);
                }else if(type == Select.class){
                    //根据方法的返回值类型来确定 单条/多条
                    Class methodReturnType = method.getReturnType();
                    if(methodReturnType == List.class){//多条 List<泛型>
                        //需要解析methodReturnType这个List中的那个泛型

                        //返回值的具体类型(java.util.List<domain.Student>)
                        Type returnType = method.getGenericReturnType();
                        //获取一个能操作泛型的对象  向下转型
                        ParameterizedTypeImpl realReturnType = (ParameterizedTypeImpl)returnType;
                        //可以操作返回值反省类
                        Type[] patternTypes = realReturnType.getActualTypeArguments();//泛型数组
                        //因为是List集合 泛型数组的第一个
                        Type patternType = patternTypes[0];
                        //还原成原来的Class
                        Class resultType = (Class)patternType;

                        return SqlSession.this.selectList(sql,param,resultType);
                    }else{//单条
                        return SqlSession.this.selectOne(sql,param,methodReturnType);
                    }
                }else{
                    System.out.println("其他注解 我处理不了");
                }
                return null;
            }
        });

        //--------------------------------------------------
//        //JDK中给我们提供好了一个类
//        //Proxy类可以帮我们创建一个代理对象
//        //想要通过下面代码创建一个代理对象
//        //需要提供三个条件
//        //  1.ClassLoader  需要一个类加载器
//        ClassLoader loader = clazz.getClassLoader();
//        //  2.Class[]      加载的类  有可能代理好多不同的类  正常的使用中  通常就代理一个类
//        Class[] interfaces = new Class[]{clazz};
//        //  3.InvocationHandler  代理对象代替你做事情的时候 具体该怎么做
//        InvocationHandler handler = new InvocationHandler(){
//            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                //代理对象的执行方法 帮真实对象做事
//                //sqlSession.insert(sql,student);
//                return null;
//            }
//        };
//        return (T)Proxy.newProxyInstance(loader,interfaces,handler);
    }

}

标签:java,封装,String,rs,pstat,ORM,sql,import,连接池
来源: https://blog.csdn.net/m0_51945027/article/details/113724269

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有