美文网首页昔我室友屌似卿
JDBC之executeQuery()方法包装(一)

JDBC之executeQuery()方法包装(一)

作者: 憧憬着的未来 | 来源:发表于2017-07-23 23:13 被阅读10次

    我不知道现在原生的JDBC是否还受欢迎,但是我目前还在使用中,但是原生的JDBC对于查询还是太不智能了,不能通过简单的参数列表什么的返回需要的结果;我只想输入查询的sql语句,返回值的类型,参数列表,就可以得到查询的结果。不需要去获取链接,释放资源什么的。
    所以,自己动手,丰衣足食是吧,开始写着一系列的包装类。

    • 获取链接
      目前最好的获取连接的方法是写一个连接池,将产生的连接保存起来,池满了进行资源的释放,这个留在以后改造
      这次只是一个简单的链接获取类,可能还有些瑕疵,想的不够周全
    /**
     * 获取链接
     */
    public class JdbcConnection {
        private static final String DRIVER = "com.mysql.jdbc.Driver";   
        private static final String URL = "jdbc:mysql://localhost:3306/mydb?user=root&password=root";
        private JdbcConnection() {} 
        /**
         * 获取数据库的链接
         * @return conn
         */
        public static Connection getJdbcConnetion() {   
            Connection conn = null;
            try {
                Class.forName(DRIVER);
                conn = DriverManager.getConnection(URL);
                
            } catch (ClassNotFoundException e) {
                System.out.println("ClassNotFoundException when loading driver");
            } catch (SQLException e) {
                System.out.println("SQLException when loading driver");
            }
            return conn;
        }   
    }
    
    • queryForObjectList(String sql, Class clazz, String... params)
      输入sql文,返回值类型,参数列表,返回一个该类型的List集合。
      设计的思路:
      sql文就不说了,查询肯定得用啊,然后就是返回值的类型,这个参数标识了你需要返回的集合类型(不知道我这样描述List<?>对不对),然后就是参数列表,当然你也可以不用穿参数列表把参数写在sql里就行了哈。
      对于返回值类型这块我是通过JAVA中的反射获取到你想要的所有信息,然后进行一系列的处理,将结果返回,但是参数列表这,我原本打算是使用Object类型的,但是实际运用的时候发现有些问题没有解决,就放弃了,使用了String类型,我就好奇,为啥方法的参数类型是Object的时候,你传一个int、String、Integer啥的都不行。。。,这块还有一种思路就是使用Map<String, Object>去承接参数进行传递,但是我想了想可能处理比较复杂就放弃了,总的来说,反射很重要,所有的操作都是进行反射来进行的。
      • 反射的入门
        1.获取Class对象

    //第一种方式
    Class.forName("类的路径+名称");
    //第二种方式
    类的名称.class;

    2.获取构造器
    - - ```
    //第一种方式,这种方式不能获取到私有的构造器
    public Constructor<?>[]  getConstructors();
    //第二种方式,这种方式可以获取到所有的构造器与权限无关
    public Constructor<?>[]  getDeclaredConstructors();
    

    3.获取方法

    //第一种方式,通过方法的名字和他的形参类型进行获取
    public Method getMethod(methodName, paramsType);
    //第二种方式,获取所有的方法
    public Method[] getDeclaredMethods();

    
    使用上边的这些反射的知识就差不多可以动手写了。
    - - 对于sql文的处理还是跟原有的一样
    - - ```
    //查询对象
    PreparedStatement preparedStatement = null;
    //结果集对象
    ResultSet resultSet = null;
    //获取查询对象
    preparedStatement = conn.prepareStatement(sql);
    /进行参数的处理
    if ((null != params) && (params.length > 0)) {
          for (int i = 0; i < params.length; i++) {
            preparedStatement.setString(i + 1, params[i]);
          }
    }
    //获得结果集
    resultSet = preparedStatement.executeQuery();
    
      • 根据返回值类型处理结果集

    //结果集处理对象
    ResultSetMetaData resultSetMetaData = null;
    //结果集处理
    resultSetMetaData = resultSet.getMetaData();
    //获取到查询列的个数
    int columnCount = resultSetMetaData.getColumnCount();

    1.返回值类型是java.lang包下的类型,根据其对应的类型直接使用对应的构造器进行返回。
    - - ```
    //返回类型是java.lang下时的处理
    if ("String".equals(clazz.getSimpleName())) {
          resultObj = new String(resultSet.getString(resultSetMetaData.getColumnName(i)));
    }
    

    2.返回值类型是自定义的类型,通过反射进行处理,然后返回

    //返回类型是自定义类型的处理
    //获取到返回类型中的所有方法
    Method[] methods = clazz.getDeclaredMethods();
    String columnName = ("set" + resultSetMetaData.getColumnName(i)).toLowerCase();
    for (int j = 0; j < methods.length; j++) {
    String methodName = methods[j].getName().toLowerCase();
    //使用对象中的setXXX()方法
    if (columnName.equals(methodName)) {
    String value = resultSet.getString(resultSetMetaData.getColumnName(i));
    //进行查询结果类型的判断
    String methodType = methods[j].getParameterTypes()[0].getName();
    switch (methodType) {
    case "java.lang.String":
    methods[j].invoke(resultObj, value);
    break;
    case "int":
    methods[j].invoke(resultObj, Integer.parseInt(value));
    break;
    case "java.lang.Integer":
    methods[j].invoke(resultObj, Integer.parseInt(value));
    break;
    case "double":
    methods[j].invoke(resultObj, Double.parseDouble(value));
    break;
    case "java.lang.Double":
    methods[j].invoke(resultObj, Double.parseDouble(value));
    break;
    default:
    break;
    }
    break;
    }
    }

    对于switch这块的处理,还有一种方法如下,但是当返回对象中的属性类型是基本类型的时候,这种方式就会存在BUG,因为没有基本类型是没有构造器的。
    - - ```
    //进行查询结果类型的判断
    Class methodType = methods[j].getParameterTypes()[0];
    //获取参数类型的构造器
    Constructor constructor = methodType.getConstructor(methodType);
    methods[j].invoke(resultObj, constructor.newInstance(resultSet.getString(resultSetMetaData.getColumnName(i))));
    
      • 测试
    id name url alexa country
    1 Goole https://www.google.com/ 1 USA
    2 淘宝 https://www.taobao.com/ 13 CN
    3 菜鸟教程 https://www.runoob.com/ 4689 CN
    4 微博 https://weibo.com/ 20 CN
    5 Facebook https://www.facebook.com/ 30 USA
    6 stackoverflow https://stackoverflow.com/ 0 IND

    该表对应的DTO为

    public class Websites implements Serializable {
    /**
    *
    /
    private static final long serialVersionUID = 8725455715197566090L;
    /
    *
    * id
    /
    private int id;
    /
    *
    * name
    /
    private String name;
    /
    *
    * url
    /
    private String url;
    /
    *
    * alexa
    /
    private String alexa;
    /
    *
    * country
    */
    private String country;
    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getUrl() {
    return url;
    }
    public void setUrl(String url) {
    this.url = url;
    }
    public String getAlexa() {
    return alexa;
    }
    public void setAlexa(String alexa) {
    this.alexa = alexa;
    }
    public String getCountry() {
    return country;
    }
    public void setCountry(String country) {
    this.country = country;
    }
    }

    要求:查询id为1的记录
    测试代码如下
    - - ```
    public class TestJdbcOperate {
          public static void main(String[] args) {
            StringBuilder sql = new StringBuilder();
            sql.append("    select id id,   ");
            sql.append("    name name,  ");
            sql.append("    url url,    ");
            sql.append("    alexa alexa,    ");
            sql.append("    country country ");
            sql.append("    from websites   ");
            sql.append("    where id = ?");
            List<Websites> reuslt = JdbcOperate.queryForObjectList(sql.toString(), Websites.class, "1");
            for(Websites websites : reuslt) {
              System.out.println(websites.getId() + ", " + websites.getName() + "," + websites.getUrl() + ", " + websites.getAlexa() + ", " + websites.getCountry());
            }
          }
    }
    

    输出结果

    1, Goole,https://www.google.com/, 1, USA

    虽然说测试成功了,但是这个方法的健壮性还得测试,我是不想把测试方法写的这么LOW的,但是不知道Junit的jar为啥build不进去就放弃了。虽然Junit用的也不6。

    相关文章

      网友评论

        本文标题:JDBC之executeQuery()方法包装(一)

        本文链接:https://www.haomeiwen.com/subject/pdxvkxtx.html