萌新的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;
}

总结

当我们没法明确获悉对象的具体类型应该要想到反射和泛型,寻找相似方法的共同性和差异性并将它们提取出来,这是一种很不错的思路。

最后天道酬勤,反射内省的使用并没有想象中那么复杂,多练多用,便是我们逐渐登高的唯一途径。


  1. 伊蕾娜世界第一!

关于JDBC中查询方法的抽取的更多相关文章

  1. jdbc基本查询方法

    jdbc操作数据库时,最基本的三种接口是Statement PreparedStatment  CallableStatement (1)Statement createStatement() cre ...

  2. Spring Data JPA的Respository接口中查询方法

  3. YII AR查询方法

    ActiveRecord类文档:http://www.yiiframework.com/doc/guide/1.1/en/database.ar 对于一个Model Post 有如下的4中查询方法,返 ...

  4. 使用JDBC从数据库中查询数据的方法

    * ResultSet 结果集:封装了使用JDBC 进行查询的结果 * 1. 调用Statement 对象的 executeQuery(sql) 方法可以得到结果集 * 2. ResultSet 返回 ...

  5. <五>JDBC_利用反射及JDBC元数据编写通用的查询方法

    此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...

  6. [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  7. 使用JDBC从数据库中查询数据

    * ResultSet 结果集:封装了使用JDBC 进行查询的结果 * 1. 调用Statement 对象的 executeQuery(sql) 方法可以得到结果集 * 2. ResultSet 返回 ...

  8. Jmeter JDBC Request 查询语句中有汉字查询结果为空的解决方法

    搜索接口我会校验返回值,查询JDBC Request 查询语句有中文字的时候查询会有问题. 解决方法很简单,在JDBC Connection Configuration的Database URL里加一 ...

  9. Java -- JDBC_利用反射及 JDBC 元数据编写通用的查询方法

    先利用 SQL 进行查询,得到结果集: 利用反射创建实体类的对象:创建对象: 获取结果集的列的别名: 再获取结果集的每一列的值, 结合 3 得到一个 Map,键:列的别名,值:列的值: 再利用反射为 ...

随机推荐

  1. Kafka与RocketMq文件存储机制对比

    一个商业化消息队列的性能好坏,其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一. 开头问题 kafka文件结构和rocketMQ文件结构是什么样子?特点是什么? 一.目录结构 Kafk ...

  2. .Net微服务实战之可观测性

    系列文章 .Net微服务实战之技术选型篇 .Net微服务实战之技术架构分层篇 .Net微服务实战之DevOps篇 .Net微服务实战之负载均衡(上) .Net微服务实战之CI/CD .Net微服务实战 ...

  3. .Net Core 实现 自定义Http的Range输出实现断点续传或者分段下载

    一.Http的Range请求头,结合相应头Accept-Ranges.Content-Range 可以实现如下功能: 1.断点续传.用于下载文件被中断后,继续下载. 2.大文件指定区块下载,如视频.音 ...

  4. 终端进程启动失败: shell 可执行文件“C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe”的路径不存在。

    因为某些原因重新安装1了vscode 和node  遇到了两个棘手的问题 ctrl + ~  打开终端提示 " 终端进程启动失败: shell 可执行文件"C:\Windows\S ...

  5. C++学习 2 指针

    指针:指针保存的是数据的地址: #include<iostream> using namespace std; int main() { //1.定义指针 int a = 10; //指针 ...

  6. redis学习笔记-02 list列表类型命令

    一.lpush key value1 value2 value3 value4(命令将一个或多个值插入到列表头部. 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作) lpush k1 ...

  7. 项目问题记录------Mabatis动态sql语句

    现在在做一个模糊查询功能,使用两个查询条件: 条件1:下拉框选择的产品名 条件2:输入框输入的用户名 需求1:下拉框的选项是从数据库里导出来的产品名,此外,添加一个选项"全部产品" ...

  8. FastAPI 学习之路(七)字符串的校验

    系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...

  9. MIPS流水线技术

    华中科技大学 - 计算机硬件系统设计 单周期指令运行动态 Instruction Fetch Instruction Decode Execution MEM Write Back 单周期时空图 设耗 ...

  10. jenkins的安装、配置使用

    1.jenkins的使用 (1).需要先下载安装JDK 配置jdk的环境 变量JAVA_HOME的值是 jdk 的安装位置, 然后下载安装tomcat 安装好了之后,打开tomcat下的bin文件夹, ...