提出问题

查询完某个表之后,一般都是把结果的每一个字段注入到一个实体类中。比如,数据库 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 实体类的注入的更多相关文章

  1. java 中利用反射机制获取和设置实体类的属性值

    摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...

  2. 使用反射机制实现jQuery调用ashx类中的指定方法

    使用反射机制实现jQuery调用ashx类中的指定方法   近期用asp.net做个小网站,但又不喜欢使用asp.net的服务器端控件,经过一番思量后确定前端采用原始的html.后台采用Linq to ...

  3. 反射、反射机制、类加载、Class类专题复习

    一.反射概念 1.反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法.反射在设计模式和框架底层都会用到. 2. ...

  4. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  5. 如何通过java反射将数据库表生成实体类?

    首先有几点声明: 1.代码是在别人的基础进行改写的: 2.大家有什么改进的意见可以告诉我,也可以自己改好共享给其他人: 3.刚刚毕业,水平有限,肯定有许多不足之处: 4.希望刚刚学习java的同学能有 ...

  6. java反射机制与动态加载类

    什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...

  7. java 使用反射在dto和entity 实体类之间进行转换

    package com.example.demo.utils; import java.lang.reflect.Method; import java.util.List; import com.e ...

  8. 利用反射将IDataReader读取到实体类中效率低下的解决办法

    最开始使用反射一个类型的各个属性,对气进行赋值的代码如下: public static List<T> ToList<T>(IDataReader reader) { //实例 ...

  9. Spring中为什么实体类不用注入

    要理解为什么不用注入,首先就清楚注入的目的是什么?如果不注入,在程序中要使用某个类对象的方法,则需要去new一个对象.然后我们调用其中的方法,众所周知"程序=算法+数据".不失一般 ...

  10. java jdbc ResultSet结果通过java反射赋值给java对象

    在不整合框架的情况下,使用jdbc从数据库读取数据时都得一个个的get和set,不仅累代码还显得不简洁,所以利用java的反射机制写了一个工具类,这样用jdbc从数据库拿数据的时候就不用那么麻烦了. ...

随机推荐

  1. 【大数据课程】高途课程实践-Day02:利用Hive SQL编写离线数仓实现可视化展示

    〇.概述 1.实现内容 使用Hive SQL编程,构造分层离线数仓 并可以通过Quick Bi进行展示 2.过程 (1)数据接⼊到ODS层 (2)进⾏ODS到DWD层数据开发 (3)进⾏ODS到DIM ...

  2. 看起来简单实际上却很牛的KMP算法:LeetCode572-另一棵树的子树

    题目描述 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树.s 的一个子树包括 s 的一个节点和这个节点的所有子孙.s 也可以看做它自身的一棵子树. 暴力解法 从 ...

  3. typora软件下载跟安装

    typora软件介绍 typora是一款文本编辑器 是目前非常火爆的文本编辑器 [下载地址](Typora 官方中文站 (typoraio.cn)) 安装操作 pj链接 注意:不要更新!!! 安装 路 ...

  4. TCPView工具

    TCPView:一个查看端口和线程的小工具.(不需安装) 主界面: 启动程序之后,你就发现TCPView将你目前在使用的所有进程都列举出来了,并时不时的会用红.黄.绿三种颜色标注某些进程: 红色代表该 ...

  5. nuxt.js实现页面刷新功能

    key 属性Key:String 或者Function key属性赋值到<router-view>,这对于在动态页面和不同路径中进行转换很有用.不同的key会使页面组件重新渲染. 设置ke ...

  6. MongoDB从入门到实战之Docker快速安装MongoDB

    前言 在上一篇文章中带领带同学们快速入门MongoDB这个文档型的NoSQL数据库,让大家快速的了解了MongoDB的基本概念.这一章开始我们就开始实战篇教程,为了快速把MongoDB使用起来我将会把 ...

  7. IOS14广告追踪

    今天回顾一个权限问题 1.工程中先导入一下两个框架 #import <AppTrackingTransparency/AppTrackingTransparency.h> #import  ...

  8. LCD副屏-CPU,内存,时显,日期显示

    文章结构: 项目概述 成品预览 项目框架 硬件资料,代码 项目槽点 -项目概述- 以前的旧模块搁置很久没用,最近看到圈子很多倒腾电脑副屏的,咱虽然没钱,但是闲啊,刚好手头有这些东西,开干. 目的: 显 ...

  9. ArcGIS实现打点、线路图、色块、自定义弹窗

    闲聊: 马上就要过年了,不知道大家过年都放几天假,小颖公司就只放8天假,就这还有一天是集体调休扣年假,就很··············还不如不放,不过庆幸最近这两周项目也做完了也没啥事,不然就静不下心 ...

  10. SpringBoot源码学习3——SpringBoot启动流程

    系列文章目录和关于我 一丶前言 在 <SpringBoot源码学习1--SpringBoot自动装配源码解析+Spring如何处理配置类的>中我们学习了SpringBoot自动装配如何实现 ...