说到ResultSet,对于有Java 开发经验的小伙伴自然是熟悉不过了,不过我相信对于大多数人来说也算是最熟悉的陌生人。从ResultSet 的取值操作大家都会,比如:

private static List<Member> select(String sql) {List<Member> result = new ArrayList<>();Connection con = null;PreparedStatement pstm = null;ResultSet rs = null;try {//1、加载驱动类Class.forName("com.mysql.jdbc.Driver");//2、建立连接con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/spring-db-demo","root","123456");//3、创建语句集pstm =  con.prepareStatement(sql);//4、执行语句集rs = pstm.executeQuery();while (rs.next()){Member instance = new Member();instance.setId(rs.getLong("id"));instance.setName(rs.getString("name"));instance.setAge(rs.getInt("age"));instance.setAddr(rs.getString("addr"));result.add(instance);}//5、获取结果集}catch (Exception e){e.printStackTrace();}//6、关闭结果集、关闭语句集、关闭连接finally {try {rs.close();pstm.close();con.close();}catch (Exception e){e.printStackTrace();}}return result;
}

这是我们在没有使用框架以前的常规操作。随着业务和开发量的增加,我们发现这样在数据持久层这样的重复代码出现频次非常高。因此,我们首先就想到将非功能性代码和业务代码分离。首先我就会想到将ResultSet 封装数据的代码逻辑分离,增加一个mapperRow()方法,专门处理对结果的封装,代码如下:

private static List<Member> select(String sql) {List<Member> result = new ArrayList<>();Connection con = null;PreparedStatement pstm = null;ResultSet rs = null;try {//1、加载驱动类Class.forName("com.mysql.jdbc.Driver");//2、建立连接con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/spring-db-demo","root","123456");//3、创建语句集pstm =  con.prepareStatement(sql);//4、执行语句集rs = pstm.executeQuery();while (rs.next()){Member instance = mapperRow(rs,rs.getRow());result.add(instance);}//5、获取结果集}catch (Exception e){e.printStackTrace();}//6、关闭结果集、关闭语句集、关闭连接finally {try {rs.close();pstm.close();con.close();}catch (Exception e){e.printStackTrace();}}return result;
}

但在真实的业务场景中,这样的代码逻辑重复率实在太高,上面的改造只能应用Member这个类,换一个实体类又要重新封装,聪明的程序猿肯定不会通过纯体力劳动给每一个实体类写一个mapperRow()方法,一定会想到代码复用方案。我们不妨来做这样一个改造,代码如下:
先创建Member 类:

@Entity
@Table(name="t_member")
@Data
public class Member implements Serializable {@Id private Long id;private String name;private String addr;private Integer age;@Overridepublic String toString() {return "Member{" +"id=" + id +", name='" + name + '\'' +", addr='" + addr + '\'' +", age=" + age +'}';}
}

对JDBC 操作优化:

public static void main(String[] args) {Member condition = new Member();condition.setName("Tom");condition.setAge(19);List<?> result =  select(condition);System.out.println(Arrays.toString(result.toArray()));
}private static List<?> select(Object condition) {List<Object> result = new ArrayList<>();Class<?> entityClass = condition.getClass();Connection con = null;PreparedStatement pstm = null;ResultSet rs = null;try {//1、加载驱动类Class.forName("com.mysql.jdbc.Driver");//2、建立连接con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/gp-vip-spring-db-demo?characterEncoding=UTF-8&rewriteBatchedStatements=true","root","123456");//根据类名找属性名Map<String,String> columnMapper = new HashMap<String,String>();//根据属性名找字段名Map<String,String> fieldMapper = new HashMap<String,String>();Field[] fields =  entityClass.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();if(field.isAnnotationPresent(Column.class)){Column column = field.getAnnotation(Column.class);String columnName = column.name();columnMapper.put(columnName,fieldName);fieldMapper.put(fieldName,columnName);}else {//默认就是字段名属性名一致columnMapper.put(fieldName, fieldName);fieldMapper.put(fieldName,fieldName);}}//3、创建语句集Table table = entityClass.getAnnotation(Table.class);String sql = "select * from " + table.name();StringBuffer where = new StringBuffer(" where 1=1 ");for (Field field : fields) {Object value =field.get(condition);if(null != value){if(String.class == field.getType()) {where.append(" and " + fieldMapper.get(field.getName()) + " = '" + value + "'");}else{where.append(" and " + fieldMapper.get(field.getName()) + " = " + value + "");}//其他的,在这里就不一一列举,下半截我们手写ORM框架会完善}}System.out.println(sql + where.toString());pstm =  con.prepareStatement(sql + where.toString());//4、执行语句集rs = pstm.executeQuery();//元数据?//保存了处理真正数值以外的所有的附加信息int columnCounts = rs.getMetaData().getColumnCount();while (rs.next()){Object instance = entityClass.newInstance();for (int i = 1; i <= columnCounts; i++) {//实体类 属性名,对应数据库表的字段名//可以通过反射机制拿到实体类的说有的字段//从rs中取得当前这个游标下的类名String columnName = rs.getMetaData().getColumnName(i);//有可能是私有的Field field = entityClass.getDeclaredField(columnMapper.get(columnName));field.setAccessible(true);field.set(instance,rs.getObject(columnName));}result.add(instance);}//5、获取结果集}catch (Exception e){e.printStackTrace();}//6、关闭结果集、关闭语句集、关闭连接finally {try {rs.close();pstm.close();con.close();}catch (Exception e){e.printStackTrace();}}return result;
}

巧妙地利用反射机制,读取Class 信息和Annotation 信息,将数据库表中的列和类中的字段进行关联映射并赋值,以减少重复代码。

从ResultSet 说起相关推荐

  1. resultset mysql_MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)...

    [声明] 欢迎转载,但请保留文章原始出处→_→ [正文] 一.ResultSet接口的介绍: 对数据库的查询操作,一般需要返回查询结果,在程序中,JDBC为我们提供了ResultSet接口来专门处理查 ...

  2. Resultset获取行数和列数

    为什么80%的码农都做不了架构师?>>>    在Java中,获得ResultSet的总行数的方法有以下几种.  第一种:利用ResultSet的getRow方法来获得ResultS ...

  3. ResultSet获取set中的记录数

    我们知道jdbc链接库之后,我们可以回遇到查询数据库的数据的情况 sql=select * from table_name; 常常都会定义一个ResultSet set=state.excuteQue ...

  4. Java获取数据库表的字段信息,及如何将ResultSet转为json

    为什么80%的码农都做不了架构师?>>>    一.Java获取数据库表的各个字段的相关信息 在某些开发情景中,需要获取数据库中表的各个字段的相关信息,如字段名,字段类型,字段大小等 ...

  5. ResultSet转List

    Role是一个实体类,传进来的sql,查询的是rule_id和rule_name两个字段,所以要指定一下具体的值 Role role = new Role(); role.setId(rs.getIn ...

  6. java resultset wasnull_Java Spring – RowMapper ResultSet – 整数/空值

    我有一个 Java SE 8 Spring 4.1.6-RELEASE应用程序,我正在实现 org.springframework.jdbc.core.RowMapper接口,我对其 T mapRow ...

  7. 将ResultSet转为List

    2019独角兽企业重金招聘Python工程师标准>>> public static List resultSetToList(ResultSet rs) throws java.sq ...

  8. Java(CallableStatement)调用Oracle存储过程返回结果集(ResultSet)

     一:无返回值的存储过程调用 存储过程: CREATE OR REPLACE PROCEDURE PRO_1(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2) AS BEGIN ...

  9. Java ResultSet如何检查是否有任何结果

    本文翻译自:Java ResultSet how to check if there are any results Resultset has no method for hasNext. 结果集没 ...

  10. Java -- JDBC 学习--通过 ResultSet 执行查询操作

    ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果. 1. 调用 Statement 对象的 executeQuery(sql) 可以得到结果集. 2. ResultSet 返回的实 ...

最新文章

  1. 点、线、面生成mvt(MapBox Vector Tile)格式的瓦片总结
  2. tomcat重启后session没有清除的解决办法
  3. 2.Azure资源组迁移
  4. HTTP 1.0 与 1.1比较
  5. 『WPF』实现拖动文件到窗体(控件)
  6. UC浏览器电脑版怎么恢复被关闭的网页
  7. 数学建模之图论——图与网络模型(一)(基本概念和最短路问题,附MATLAB源码)
  8. mysql怎么分组计算逾期率_转行数据分析第三篇:mysql查询入门练习题
  9. python——Django(ORM连表操作)
  10. X 射线技术揭示芯片的秘密!
  11. Thinkphp3.2在IIS中使用ISAPI_Rewrite去除index.php
  12. 从大哥大到iPhone13,谈谈移动网络发展
  13. 图像匹配之归一化积相关灰度匹配
  14. Selenium无法定位的6种解决方案
  15. 第二重要极限公式推导过程_机器学习——一文详解逻辑回归「附详细推导和代码」...
  16. AOSP AOKP CM
  17. Postaman 报错:Could not get the lock, quitting
  18. SAP管理软件系统框架合同业务的实现及相关注意事项解析
  19. 一、剪辑行业概述与剪辑工具介绍
  20. Mysql数据库-表的增、删、查、改

热门文章

  1. System.IO 的三个抽象类
  2. redis之五大数据类型
  3. Code Complete
  4. Memcached 数据缓存系统
  5. django学习资料网址汇总
  6. [转载]内容首页设计经验
  7. aliyun 阿里云Maven仓库地址 不管是自建私服还是maven构建 必备 结束了几kb的历史
  8. Error response from daemon: manifest not found.
  9. Java 面试题 —— 老田的蚂蚁金服面试经历
  10. Mac上配置React Native