首页 > 其他分享 >通过反射机制简化 JDBC ResultSet 实体类 setter

通过反射机制简化 JDBC ResultSet 实体类 setter

时间:2022-10-18 16:35:07浏览次数:73  
标签:实体类 rs getName ResultSet field JDBC new

提出问题

JDBC 中查询的数据存储在 ResultSet 中,一般来说,需要有一个实体类来承载 ResultSet 的数据。比如,数据库有一个 users 表,查询出来的结果肯定是要注入到 User 实体类中的。

一般的做法就是通过 while 遍历 ResultSet,通过getString()(或其他对应类型的 getter)注入到实体类中(实体类的 setter)。难道每一个表的查询都要重新写一个重复的注入实体类的操作代码吗?通过反射机制我们可以简化这样的操作。

问题案例

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;
  }

如果是 Student 实体类,那么 while 体内的代码又要修改,十个不同的实体类就修改十次,并且字段又多,太麻烦!

通过反射解决问题

最重要的是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);
  } 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()));
}

不管实体类字段有多少个,都不需要一个个去 setter 和 getter,这样做起来简直太方便了。而且,因为使用了泛型,实体类的类型也是可以改变的,比如说查询的表是 students,那么把类型换成 Student 就可以了。

image

补充说明

在测试函数中,new LoadConfig<>(MySQLConfig.class).getConfig()不是什么官方的工具函数,而是我自己写的一个方便配置数据库的加载配置类。具体实践我在另一篇随笔中有详细阐述:认识注解带来的好处,如何通过注解简化程序

理解本随笔中举的案例,最好是看源码,所以这里是

标签:实体类,rs,getName,ResultSet,field,JDBC,new
From: https://www.cnblogs.com/Enziandom/p/16803036.html

相关文章

  • JDBC管理事务-概述和JDBC管理事务-实现
    JDBC管理事务-概述JDBC控制事务:1.事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这个步骤要么同时成功,要么同时失败。2.操作:1.开启事务2......
  • JDBC事务管理概述和实现
    1.事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。2.操作: 1.开启事务 2.提交事务 3.回滚事务3.使......
  • JDBC工具类-JDBC练习-登录案例
    *目的:简化书写*分析: 1.注册驱动也抽取 2.抽取一个方法获取连接对象 *需求:不想传递参数(麻烦),还得保证工具类的通用性。 *解决:配置文件 ......
  • JDBC练习-select语句和JDBC工具类
    JDBC练习-select语句练习:定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。1.定义Emp类封装Emp表数据的JavaBean2.实现方法public List<Emp>findA......
  • JDBC工具类
        ......
  • map集合类型/实体类类型的参数
    map集合类型的参数若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意${......
  • JDBC
    JDBC概念:JDBC就是使用Java语言操作关系型数据库的一套API全称:(JavaDataBaseConnectivity)Java 数据库连接JDBC本质:官方(sun公司)定义的一套操作所有关系型数据库的规则......
  • 554JDBC事务管理 Jdbc事务管理 and555JDBC管理事务_概述 556JDBC管理事务实现
    JDBC事务管理1.Preparedstatement:执行sql的对象1.SQL注入问题:在拼接sql时,有一些的sql的特殊关键字参与字符串的拼接。会造成安全性问题2.用户随便输入:例如dawug......
  • JdbcConfig
    JdbcConfigjdbc.properties注解版@Value("${jdbc.driver}")privateStringdriver;@Value("${jdbc.url}")privateStringurl;@Value("${jdbc.use......
  • day49-JDBC和连接池05
    JDBC和连接池0511.BasicDAO先来分析一个问题前面我们使用了Apache-DBUtils和Druid简化了JDBC开发,但仍存在以下不足:SQL语句是固定的,不能通过参数传入,通用性不好,需要......