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<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。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,577评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,789评论 0 11
  • 小编费力收集:给你想要的面试集合 1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JA...
    八爷君阅读 4,573评论 1 114
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,597评论 18 139
  • 《怎寻》若·初(388) 山山水水千万重, 青山怎知西楼梦? 游云过海遇故人, 却叹难回旧风尘。 《莫回》若·初(...
    若初虹阅读 171评论 0 0