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

我不知道现在原生的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去承接参数进行传递,但是我想了想可能处理比较复杂就放弃了,总的来说,反射很重要,所有的操作都是进行反射来进行的。
    • 反射的入门
      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 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()方法包装(一))