关于JDBC中查询方法的抽取
萌新的JAVA学习笔记[1]
先来张伊蕾娜镇场~~

简单描述
起初我们的查询方法时分为单个查询和全部查询,过于局限与繁琐,如此一来我们能不能想一个办法将所有类型的查询抽取出来并整合成为一个单独的工具方法,并使之具有较为方便的通用性。
-----------------------------------------------------------------------------------
思路整理
想要进行整合,首先我们得先寻找其中的差异点,以及共同点;
共同点:
都需要SQL语句;
都需要获取连接对象;
都需要获取结果集对象;
都需要获取语句对象;
都需要将从SQL语句中读到的数据信息赋给用于封装数据的对象;
以及都需要关闭资源。
差异点:
查询范围不同;
因为查询范围不同而导致的SQL语句不同;
传入的参数不同;
返回的值类型不同(但都可以用集合接收输出)。
| 如此一来,思路便逐渐清晰了起来 |
但同时又面临新的问题,因为通用性问题,我们并不知道我们所用来封装数据的时候所用到的对象的类型,这里很容易让人想到反射以及泛型;
同时,我们也并不知道当执行查询的时候所用到的SQL语句的参数是什么类型,这里我们可以用Object...params数组来解决。
那么,我们便开始吧~~
分步明晰
首先,是我们的方法所需要传入的参数,第一个就是我们执行SQL所需要使用的SQL语句了,这个需要调用者根据不同的查询范围自行传入;
第二个便是我们用来封装对象的类的字节码对象了,这个在我们使用内省操作字段的时候需要使用,因为不知道对象类型,所以我们这里使用泛型;
最后我们再设置SQL语句执行所需要调用的参数,因为参数类型繁多,我们这里使用Object...params,代表传入的值可以有0-n个。
java String sql, Class<T> type, Object...params
再接着,是各个对象的声明(在外面声明,不然在之后没法关)以及用来接收封装数据对象的集合的创建,这里使用上面声明的泛型;
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list = new ArrayList<>();
然后是不厌其烦的获取连接对象以及语句对象,这里使用我们已经写好的获取连接对象的方法;
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
再接下来,是为传入的SQL语句的占位符"?"设置值,这里使用循环遍历params数组就行了;
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
下面我们来获取结果集对象,再对它进行遍历,使用getObject方法将其中的数据取出来,然后通过内省将数据封装进对象中,最后再用list集合接收;
rs = ps.executeQuery();
// 直到next方法返回false时结束
while (rs.next()) {
// 获取这一行中的指定列的数据
//使用反射创建对象
T t = type.newInstance();
//将数据从结果集中获取到,并设置给对象t
//通常情况下,属性名和列名一样,所以我们可以根据属性名去获取对应列的值
BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass(),
Object.class);
PropertyDescriptor[] pds =
beanInfo.getPropertyDescriptors();
//操作每个属性
for (PropertyDescriptor pd : pds) {
//获取到属性名
String name = pd.getName();
//根据这个属性名从结果集中获取到数据
Object value = rs.getObject(name);
//获取到属性对应的set方法
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(t, value);
}
list.add(t);
因为这步中的代码有点长,所以我们来稍微解析一下循环中内容。
首先获取实例对象到获取类中的属性就不细说了,然后是遍历获取到的包含了所有属性的描述器数组;
获取属性名之后通过getObject得到我们所需要的属性所对应的值,再通过各个属性描述器获取到对应属性的set方法;
最后调用invok方法将遍历结果集得到的值传入,并将的到的对象存入集合中。
完整代码
/**
* 处理查询操作
* <T>:是声明泛型类型
* List<T>, Class<T>使用声明好的T
* @param sql 要执行的SQL语句
* @param type 将每行数据封装的对象类型
* @param params 执行的SQL需要的参数
* @return 返回查询到的结果,统一放到List集合中
*/
public static <T> List<T> executeQuery(String sql, Class<T> type, Object...params){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<T> list = new ArrayList<>();
try {
conn = JDBCUtil.getConnection();
ps = conn.prepareStatement(sql);
//为占位符设值
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
rs = ps.executeQuery();
// 直到next方法返回false时结束
while (rs.next()) {
// 获取这一行中的指定列的数据
//使用反射创建对象
T t = type.newInstance();
//将数据从结果集中获取到,并设置给对象t
//通常情况下,属性名和列名一样,所以我们可以根据属性名去获取对应列的值
BeanInfo beanInfo = Introspector.getBeanInfo(t.getClass(),
Object.class);
PropertyDescriptor[] pds =
beanInfo.getPropertyDescriptors();
//操作每个属性
for (PropertyDescriptor pd : pds) {
//获取到属性名
String name = pd.getName();
//根据这个属性名从结果集中获取到数据
Object value = rs.getObject(name);
//获取到属性对应的set方法
Method writeMethod = pd.getWriteMethod();
writeMethod.invoke(t, value);
}
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtil.close(conn, ps, rs);
}
return list;
}
总结
当我们没法明确获悉对象的具体类型应该要想到反射和泛型,寻找相似方法的共同性和差异性并将它们提取出来,这是一种很不错的思路。
最后天道酬勤,反射内省的使用并没有想象中那么复杂,多练多用,便是我们逐渐登高的唯一途径。
伊蕾娜世界第一! ︎
关于JDBC中查询方法的抽取的更多相关文章
- jdbc基本查询方法
jdbc操作数据库时,最基本的三种接口是Statement PreparedStatment CallableStatement (1)Statement createStatement() cre ...
- Spring Data JPA的Respository接口中查询方法
- YII AR查询方法
ActiveRecord类文档:http://www.yiiframework.com/doc/guide/1.1/en/database.ar 对于一个Model Post 有如下的4中查询方法,返 ...
- 使用JDBC从数据库中查询数据的方法
* ResultSet 结果集:封装了使用JDBC 进行查询的结果 * 1. 调用Statement 对象的 executeQuery(sql) 方法可以得到结果集 * 2. ResultSet 返回 ...
- <五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...
- [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 使用JDBC从数据库中查询数据
* ResultSet 结果集:封装了使用JDBC 进行查询的结果 * 1. 调用Statement 对象的 executeQuery(sql) 方法可以得到结果集 * 2. ResultSet 返回 ...
- Jmeter JDBC Request 查询语句中有汉字查询结果为空的解决方法
搜索接口我会校验返回值,查询JDBC Request 查询语句有中文字的时候查询会有问题. 解决方法很简单,在JDBC Connection Configuration的Database URL里加一 ...
- Java -- JDBC_利用反射及 JDBC 元数据编写通用的查询方法
先利用 SQL 进行查询,得到结果集: 利用反射创建实体类的对象:创建对象: 获取结果集的列的别名: 再获取结果集的每一列的值, 结合 3 得到一个 Map,键:列的别名,值:列的值: 再利用反射为 ...
随机推荐
- urllib2获取CGI请求的数据
import urllib.request as urllib2 headers = { 'Authorization': 'Basic YWRtaW46YWRtaW4=', }#需要身份验证时,在请 ...
- [转载]用redis实现跨服务器session
地址:http://blog.chinaunix.net/uid-11121450-id-3284875.html 这个月我们新开发了一个项目,由于使用到了4台机器做web,使用dns做负载均衡, 上 ...
- HTML 网页开发、CSS 基础语法—— 一. HTML概述(了解网页)
1. 网页的本质 ① HTML就是用来制作网页文件的. ② 浏览器查看的网页都是.html或.htm文件. ③ HTML叫做超文本标记语言(Hypertext Markup Language),用于搭 ...
- 关于我刚开始学习c语言的这档事
关于我刚开始学习C语言的这档事 就在9月20日下午,记得王老师曾提及三类人,一类专注于自己内心的感受:一类人专注于探索与创造:还有一类专注于效率的最大化.思绪不禁回想到11号至今的学习过程-- 我的学 ...
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
- Redis之品鉴之旅(五)
Redis事务 原子性:就是最小的单位 一致性:好多命令,要么全部执行成功,要么全部执行失败 隔离性:一个会话和另一个会话之间是互相隔离的 持久性:执行了就执行了,数据保存在硬盘上 典型例子:银行转账 ...
- Markdown学习 Day 001
Markdown学习 Day 001 快速标题 "#" + "空格" + "标题内容",回车即可,PS. "#"数量n代 ...
- Windows 11 正式版 Build 22000.194 官方简体中文版、英文版(消费者版、商业版)下载
昨天阿三正式发布了 Windows 11,版本号竟然是 22000.194,也就是 9 月 16 日的 测试版 22000.194,仅仅是文件改了个名,特别是消费者版本 hash 校验都是一致的. W ...
- MySQL技术专题(X)该换换你的数据库版本了,让我们一同迎接8.0的到来哦!(初探篇)
前提背景 MySQL关是一种关系数据库管理系统,所使用的 SQL 语言是用于访问数据库的最常用的标准化语言,其特点为体积小.速度快.总体拥有成本低,尤其是开放源码这一特点,在 Web应用方面 MySQ ...
- 3D渲染
3d渲染的本质是在三维坐标系中绘制很三角形,用三角形拼成物体,然后投影到二维图像上,所以做渲染就是画好这些三角形;3d渲染输入的是很多三角形的3个顶点和属性,输出的是一张2d图.画好三角形要研究给三角 ...