关于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,键:列的别名,值:列的值: 再利用反射为 ...
随机推荐
- Spring Cloud Gateway 没有链路信息,我 TM 人傻了(下)
本系列是 我TM人傻了 系列第五期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...
- centos7 kubeadm 搭建k8s
Centos 7 搭建 kubernetes 集群环境 一.介绍 本次是centos7 搭建kubernetes1.15.9 通过kubeadm 的形式搭建 二.准备 > centos 7 (镜 ...
- ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探
前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...
- Python setattr() 函数 ,Python super() 函数: Python 内置函数 Python 内置函数
描述 setattr 函数对应函数 getatt(),用于设置属性值,该属性必须存在. 语法 setattr 语法: setattr(object, name, value) 参数 object -- ...
- kubelet源码分析——启动Pod
前文说到Kubelet启动时,调用到kubelet.Run方法,里面最核心的就是调用到kubelet.syncLoop.它是一个循环,这个循环里面有若干个检查和同步操作,其中一个是地在监听Pod的增删 ...
- 从Gartner与IDC三大行业报告,看国产RPA的市场规模与未来发展
从Gartner与IDC三大行业报告,看国产RPA的市场规模与未来发展 Gartner与IDC的三份报告,描绘出中国RPA的市场规模与未来宏图 文/王吉伟 近期的国产RPA,可谓捷报频频.三个重量级行 ...
- 智汀家庭云-开发指南Golang:设备模块
1.品牌 品牌指的是智能设备的品牌,SA通过插件的形式对该品牌下的设备进行发现控制.理论上来说一个品牌对应一个插件服务.您可以通过项目 根目录下的品牌查看SA支持的品牌.关于插件服务的详细信息可以参考 ...
- ANTLR学习(一)ANTLR简介和环境搭建
一.ANTLR简介和学习动机 1. ANTLR简介 antlr是指可以根据输入自动生成语法树并可视化的显示出来的开源语法分析器.ANTLR-Another Tool for Language Reco ...
- 借助Cookie实现是否第一次登陆/显示上次登陆时间
Cookie实现是否第一次登陆/显示上次登陆时间 最近刚好看到Cookie这方面知识,对Servlet部分知识已经生疏,重新翻出已经遗弃角落的<JavaWeb开发实战经典>,重新温习了Co ...
- django3上线部署踩的坑
好久没有用过django写项目了,最近公司开发个官网,一时兴起就拿来练练手,这不用不知道,一用吓一跳啊. 才多久,版本都到3.0了. 踩坑一:运行项目时失败报错,后来查找资料发现, 当你使用djang ...