提出问题

查询完某个表之后,一般都是把结果的每一个字段注入到一个实体类中。比如,数据库 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. 【Hive】概念、安装、数据类型、DDL、DML操作、查询操作、函数、压缩存储、分区分桶、实战Top-N、调优(fetch抓取)、执行计划

    一.概念 1.介绍 基于Hadoop的数据仓库工具,将结构化数据映射为一张表,可以通过类SQL方式查询 本质:将HQL转换成MapReduce程序 Hive中具有HQL对应的MapReduce模板 存 ...

  2. K8s架构|全面整理K8s的架构介绍

    K8S架构与核心技术介绍 1. 架构图 1.1 整体结构图 1.2 组件间的协议 CNI: CNI是Container Network Interface的是一个标准的,通用的接口 ;用于连接容器管理 ...

  3. Docker的作用

    绝大部分应用,开发者都可以通过docker build创建镜像,通过docker push上传镜像,用户通过docker pull下载镜像,用docker run运行应用. 用户不需要再去关心如何搭建 ...

  4. 想做长期的 AB 实验?快来看看这些坑你踩了没

    作者:江颢 1.什么是长期的 AB 实验 大部分情况下,我们做的 AB 实验都是短期的,一到两周或者一个月之内的,通过分析这段时期内测得的实验效应得出实验结论,并最终进行推广. 长期实验即运行时间达数 ...

  5. 使用Prometheus监控docker compose方式部署的ES

    需求 收集 ES 的指标, 并进行展示和告警; 现状 ES 通过 docker compose 安装 所在环境的 K8S 集群有 Prometheus 和 AlertManager 及 Grafana ...

  6. js节流防抖 减少服务器请求

  7. angular配置多个系统 配置动态路由,缩短模块初次加载时间,快速打开界面,优化用户访问体验

    1.配置一个文件,返回系统名称 2.配置routes-routing.module.ts 引入文件 const system = 服务.getsystem() const allROUTES: {UR ...

  8. 模拟BS服务器分析-模拟BS服务器代码实现

    模拟BS服务器分析 模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果. 服务器要给客户端回写一个信息,回写一个html页面(文件)我们需要读取index.html文件,就必须的知道这个 ...

  9. 行为型模式 - 观察者模式Observer

    学习而来,代码是自己敲的.也有些自己的理解在里边,有问题希望大家指出. 有一个大佬视频中提过一个案例,我觉得很棒:遥闻深巷中犬吠,边有妇人惊觉欠伸,其夫呓语.继而儿醒,大啼.夫亦醒. 模式的定义与特点 ...

  10. 【分析笔记】全志平台 gpio_wdt 驱动应用和 stack crash 解决

    使用说明 第一次遇到看门狗芯片是通过切换电平信号来喂狗,如 SGM706 芯片,之前也比较少会用到看门狗芯片.原本打算参考 sunxi-wdt.c 的框架,利用定时器自己写一个,无意中发现内核已经有 ...