通过反射机制简化 JDBC ResultSet 实体类的注入
提出问题
查询完某个表之后,一般都是把结果的每一个字段注入到一个实体类中。比如,数据库 users 表,查询出来的结果注入到 User 实体类中。
通过 while 遍历 ResultSet,把字段对应的类型通过对应的方法getXxx()注入到实体类中。每一个实体类的字段都不一样,又重新写重复的注入实体类的操作代码,是非常麻烦的,幸好有反射机制可以简化这样的操作。
问题案例
public List<User> selectAll() {
List<User> users = new ArrayList<>();
try {
Connection connection = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
PreparedStatement statement = connection.prepareStatement("select * from users");
ResultSet rs = statement.executeQuery();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setAge(rs.getInt("age"));
user.setAvatar(rs.getString("avatar"));
user.setShow_name(rs.getString("show_name"));
users.add(user);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return users;
}
students 表的查询结果,注入数据到 Student 实体类中。users 表,又得写差不多的重复代码,也只是 new 实体类以及循环体内的注入代码发生了变化。
通过反射解决问题
jnject专门来处理如何把 ResultSet 结果注入到实体类中。需要传递一个实体类的反射对象,类型是泛型:
private List<T> inject(ResultSet rs, Class<T> clz) {
List<T> list = new ArrayList<>();
try {
while (rs.next()) {
T t = clz.getDeclaredConstructor().newInstance();
for (Field field : clz.getDeclaredFields()) {
field.setAccessible(true);
if (field.getType().getName().equals(String.class.getName())) {
field.set(t, rs.getString(field.getName()));
} else if (field.getType().getName().equals(int.class.getName())) {
field.set(t, rs.getInt(field.getName()));
} else if (field.getType().getName().equals(java.util.Date.class.getName())) {
field.set(t, rs.getDate(field.getName()));
}
}
list.add(t);
}
} catch (SQLException | InvocationTargetException | InstantiationException | IllegalAccessException |
NoSuchMethodException e) {
throw new RuntimeException(e);
}
return list;
}
通过反射创建实体类对象,再获取这个实体类对象的所有字段,不管你是 private、public、protected 修饰的字段都可以获取,所以,必须通过getDeclaredFields()函数来获取对象的字段。
在 for 循环体中,我做了一个判断,判断实体类字段的类型是什么类型,针对类型去从结果集中获取相应类型的值,再通过 Field 对象的set函数给实体类的属性注入值。
public List<T> selectAll(Class<T> clz) {
List<T> list;
try {
Connection connection = DriverManager.getConnection(config.getUrl(), config.getUsername(), config.getPassword());
PreparedStatement statement = connection.prepareStatement("select * from users");
list = inject(statement.executeQuery(), clz); // 调用 inject 函数,完成实体类注入
} catch (SQLException e) {
throw new RuntimeException(e);
}
return list;
}
测试函数
public static void main(String[] args) {
MySQLConfig config = new LoadConfig<>(MySQLConfig.class).getConfig();
List<User> users = new Simple<User>(config).selectAll(User.class);
System.out.println(Arrays.toString(users.toArray()));
}
在使用层面上,我们无需再关注如何把结果集注入到实体类中,而只需要提供一个实体类的反射对象即可完成查询操作。

补充说明
在测试函数中,new LoadConfig<>(MySQLConfig.class).getConfig()是我写的一个方便配置数据库的配置加载工具类。具体实践我在另一篇随笔中有:注解带来的好处,注解如何简化代码。
这里是GitHub 仓库的源码地址。
通过反射机制简化 JDBC ResultSet 实体类的注入的更多相关文章
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
- 使用反射机制实现jQuery调用ashx类中的指定方法
使用反射机制实现jQuery调用ashx类中的指定方法 近期用asp.net做个小网站,但又不喜欢使用asp.net的服务器端控件,经过一番思量后确定前端采用原始的html.后台采用Linq to ...
- 反射、反射机制、类加载、Class类专题复习
一.反射概念 1.反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法.反射在设计模式和框架底层都会用到. 2. ...
- 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换
作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...
- 如何通过java反射将数据库表生成实体类?
首先有几点声明: 1.代码是在别人的基础进行改写的: 2.大家有什么改进的意见可以告诉我,也可以自己改好共享给其他人: 3.刚刚毕业,水平有限,肯定有许多不足之处: 4.希望刚刚学习java的同学能有 ...
- java反射机制与动态加载类
什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...
- java 使用反射在dto和entity 实体类之间进行转换
package com.example.demo.utils; import java.lang.reflect.Method; import java.util.List; import com.e ...
- 利用反射将IDataReader读取到实体类中效率低下的解决办法
最开始使用反射一个类型的各个属性,对气进行赋值的代码如下: public static List<T> ToList<T>(IDataReader reader) { //实例 ...
- Spring中为什么实体类不用注入
要理解为什么不用注入,首先就清楚注入的目的是什么?如果不注入,在程序中要使用某个类对象的方法,则需要去new一个对象.然后我们调用其中的方法,众所周知"程序=算法+数据".不失一般 ...
- java jdbc ResultSet结果通过java反射赋值给java对象
在不整合框架的情况下,使用jdbc从数据库读取数据时都得一个个的get和set,不仅累代码还显得不简洁,所以利用java的反射机制写了一个工具类,这样用jdbc从数据库拿数据的时候就不用那么麻烦了. ...
随机推荐
- 秒级查询之开源分布式SQL查询引擎Presto实操-上
@ 目录 概述 定义 概念 架构 优缺点 连接器 部署 集群安装 常用配置说明 资源管理安装模式 安装命令行界面 基于Tableau Web 连接器 使用优化 数据存储 查询SQL优化 无缝替换Hiv ...
- Elasticsearch模糊查询、多字段in查询、时间范围查询,DSL和java API两种方式
Elasticsearch模糊查询.多字段in查询.时间范围查询,DSL和java API两种方式 项目场景: Elasticsearch模糊查询某字段.多字段in查询.时间范围查询,通过DSL和ja ...
- Qt从实习到搬砖
Qt C++ 工具箱 从零开始的Qt开发之路 里面大概会写一些和Qt相关的内容,也不说是从0开始,感觉Qt做东西和用 C#也差不了很多?也许吧,总之慢慢来,一步一个脚印,直到给它拿下. 2022.5. ...
- [python] Python map函数总结
Python map函数总结 本文主要介绍如何使用Python(Python3版本)的内置map()函数.简单来说map()函数会将指定的函数依次作用于某个序列的每个元素,并返回一个迭代器对象.map ...
- python之路45 初识django框架
纯手撸web框架 1.web框架的本质 理解1:连接前端与数据库的中间介质 理解2:socket服务端 2.手写web框架 1.编写socket服务端代码 2.浏览器访问响应无效>>> ...
- (7)go-micro微服务zap日志配置
目录 一 Zap日志介绍 二 Zap日志安装 三 Zap日志初始化 四 Zap日志重写方法 五 Zap日志使用 六 最后 一 Zap日志介绍 Zap是在 Go 中实现超快.结构化.分级的日志记录. Z ...
- [C++Primer] 第二章 变量和基本类型
第二章 变量和基本类型 引用 引用定义的时候必须初始化. 引用初始化之后无法重新绑定到其它对象上. 引用本身并不是对象,所以没有指向引用的引用(不管如何多层引用,引用的还是源对象) 下面用一个简单的例 ...
- VS2019注册码
Visual Studio 2019 Enterprise BF8Y8-GN2QH-T84XB-QVY3B-RC4DF Visual Studio 2019 Professional NYWVH-HT ...
- 《Effective C++》模版与泛型编程
Item41:了解隐式接口和编译期多态. 纵使你从未使用过templates,应该不陌生"运行期多态"和"编译期多态"之间的差异.因为它类似于"哪一个 ...
- 震网(Stuxnet)病毒深度解析:首个攻击真实世界基础设施的病毒
摘要:震网病毒主要是通过改变离心机的转速,来破坏离心机,并影响生产的浓缩铀质量. 本文分享自华为云社区<[安全技术]震网(Stuxnet)病毒深度解析:首个攻击真实世界基础设施的病毒(1)[原创 ...