通过反射机制简化 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从数据库拿数据的时候就不用那么麻烦了. ...
随机推荐
- 【Java SE进阶】Day02 Collection、Iterator、泛型
一.Collection集合 1.概述 数组存元素,集合存对象(类型可以不一样) 2.框架分类 单列:Collection List ArrayList LinkedList Set HashSet ...
- java抽象类的定义和使用
1. 抽象类的规则 ● 抽象类不可以被实例化,也就是不能被new,会出现编译错误.抽象类如果想实例化可以通过非抽象子类的方式去实现. ● 抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类.而且抽 ...
- go-carbon 1.5.0 版本发布,修复已知 bug 和新增德语翻译文件
carbon 是一个轻量级.语义化.对开发者友好的golang时间处理库,支持链式调用. 目前已被 awesome-go 收录,如果您觉得不错,请给个star吧 github:github.com/g ...
- SpringBoot源码2——SpringBoot x Mybatis 原理解析(如何整合,事务如何交由spring管理,mybatis如何进行数据库操作)
阅读本文需要spring源码知识,和springboot相关源码知识 对于springboot 整合mybatis,以及mybatis源码关系不密切的知识,本文将简单带过 系列文章目录和关于我 涉及到 ...
- Jmeter 之 jp@gc - Stepping Thread Group
jp@gc - Stepping Thread Group 自定义线程组,根据业务需要进行设计用户增加间隔时间等 1. 下载jmeter-plugins-manager-1.3.jar插件放入lib ...
- C++进阶(位图+布隆过滤器的概念和实现+海量数据处理)
位图 概念 位图: 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景.通常是用来判断某个数据存不存在的. 适用场景: 如果我们需要对大量的数据进行处理,判断该数据在不在,比如40 ...
- Java基础篇——集合框架
集合--对象的容器 集合与数组相似,不同的是,集合的长度可变并且只能组合引用类型数据,如果要组合基本类型,则需要装箱成包装类 Collection体系集合 Collection父接口 Collecti ...
- 第一个shell
首先进入linux系统,打开命令行,输入命令vi test.sh创建一个shell测试脚本,键入i切换vi编辑器为输入模式,输入以下文本内容,键入:wq保存退出即可.下面第一行的#!是告诉系统其后路径 ...
- 经典问题 1 —— DAG 上区间限制拓扑序
问题描述 给定一个 DAG,求一个拓扑序,使得节点 \(i\) 的拓扑序 \(\in [l_i,r_i]\). 题解 首先进行一个预处理:对于所有 \(u\),令 \(\forall (v,u)\in ...
- angular小练习--手写弹出窗口以及文件上传或者复制粘贴,后读取打印文件内容
实现代码如下 <page-header> <ng-template> </ng-template> </page-header> <div> ...