文档章节

[JDBC] 处理ResultSet,构建Java对象

kailuncen
 kailuncen
发布于 2017/05/22 22:48
字数 1075
阅读 505
收藏 1

背景

最近在学习Mybatis,Mybatis在处理JDBC返回值与Java业务对象之间的转换非常方便,定义XML,标明互相之间的转换关系,即可轻松完成转换。

Mybatis是JDBC的封装,我们先来看看如果用原生的JDBC,如何完成ResultSet和Java业务对象之间的转换,会遇到哪些不便。

示例代码

Java业务PO 

CityPO,包含三个字段 id,cityId,cityName。我们会写使用原生的JDBC来获取返回值。

Integer id;

Long cityId;

String cityName;

获取返回值

Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/demo", "root", "123456");

PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM SU_City limit 10");
preparedStatement.execute();

ResultSet resultSet = preparedStatement.getResultSet();  //从数据库获取的数据
ResultSetMetaData meta = resultSet.getMetaData();        //从数据库返回的数据的元数据,包含列的基本信息
int cols = meta.getColumnCount();        

List<CityPO> cityPOS = new ArrayList<CityPO>();

对象转换

我们要完成的工作就是将ResultSet转换为cityPOS。

方案一

一个比较笨的方法,就是依次判断每个列的名字,因为开发者知道数据库的哪一列对应的是业务PO中的哪个属性,如果列名和属性名相等,那么调用对应属性的set方法,如下面的代码所示。

while (resultSet.next()) {
    CityPO cityPO = new CityPO();
    for (int i = 1; i <= cols; i++) {
		if (meta.getColumnName(i).equals("id")) {
			cityPO.setId((Integer) resultSet.getObject(i));
		} else if (meta.getColumnName(i).equals("city_id")) {
			cityPO.setCity_id(Long.valueOf((Integer)resultSet.getObject(i)));
		} else if (meta.getColumnName(i).equals("city_name")) {
			cityPO.setCity_name((String) resultSet.getObject(i));
		}
		cityPOS.add(cityPO);
	}
}

缺点

1.转换完全和具体的业务类绑定在了一起,你如果新处理一个业务类,你得再重新写一套差不多的代码,而且随着类的属性字段的增多,你的if/else代码会越来越多,听起来是不是很恐怖。

2.在调用set方法时,我们需要处理类型转换,又是一长串的代码。我们这个方案没用反射,不知道set属性的类型,只能靠人为判断,很有可能出现异常。

我在cityPO.setCity_id(Long.valueOf((Integer)resultSet.getObject(i))) 就遇到了把Integer直接强转Long失败,报出了异常才改成了现在这样,如果这样的代码出现在你应用的各个角落,你慌不?

结论

方案1的处理和具体的代码绑定的比较死,依靠一堆判断来完成赋值,那么我们想到可以利用反射来完成对属性的赋值,这样字段再多,也不怕啦。

方案二

利用反射,通过mysql字段的名称,直接反射找到对应属性的set方法,执行调用。简单的代码如下所示。

Class<?> clazz = Class.forName("po.CityPO");
Object obj = clazz.newInstance();
for (int i = 1; i <= cols; i++) {
    Field field = null;
	field = clazz.getDeclaredField(meta.getColumnName(i));
	field.setAccessible(true);
	field.set(obj, resultSet.getObject(i));
}
cityPOS.add((CityPO) obj);

这段我为了测试,是直接把对应的对象的属性名改成了数据库中的列名。

缺点

1.因为是通过数据库的列名反射出对应的方法,而通常我们在Java中使用的是驼峰命名,怎么处理列名到对象类名的转换,这里应该有一定的代码量,当然也可以在select的时候 as成对应的属性名,这样就解决了这个问题。

2.我们依然需要处理类型转换。

3.我们可能会多选了一些列,而这个方案会统统去找反射的方法,可能会抛出异常。

结论

我觉得这应该是框架会采取的方案。

 

总结

直接用原生的JDBC完成数据库到Java业务对象的转换,肯定是非常繁琐的,从目前来看,框架应该也是用的方案2,只不过会比方案案强大的多。

从使用Mybatis这一段时间来看,其在这个方案做了这么几件事。

1. 解决了数据库列名到Java列名的映射。

2.解决了数据库类型到Java类型的转换工作。

3.在转换过程中具备一定的容错能力。

 

后续

后续会研究下Mybatis在这方面所做的工作和源码,有兴趣可以持续关注。

------------------------------------------------------------------------------

© 著作权归作者所有

kailuncen
粉丝 89
博文 17
码字总数 28778
作品 0
卢湾
后端工程师
私信 提问
java使用原生jdbc连接数据库并操作

使用Java连接数据库需要使用JDBC驱动。JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的...

hasagei
01/23
0
0
java开发中jdbc连接数据 库的操作代码

JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1、加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.lang.Cla...

颜建海
2014/04/04
0
0
Commons DbUtils

1 概述 Commons DBUtils类库是小型的设计于易于使用JDBC的类集合。JDBC资源清理是平凡的,容易出错,以至于这些类从你的代码中抽象出清理代码,剩下你最初真正想要使用JDBC做的代码:查询和更...

Leech
2015/07/21
0
0
JDBC(Java Data Base Connectivity,java数据库连接)

JDBC是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。 Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法,JDBC对...

冰雷卡尔
2012/06/03
0
0
spring中的JdbcTemplate简单记录

JdbcTemplate主要提供以下五类方法: execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句; update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate...

刘谱_smile
2015/07/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Angular 英雄编辑器

应用程序现在有了基本的标题。 接下来你要创建一个新的组件来显示英雄信息并且把这个组件放到应用程序的外壳里去。 创建英雄组件 使用 Angular CLI 创建一个名为 heroes 的新组件。 ng gener...

honeymoose
今天
5
0
Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
6
0
hive

一、hive的定义: Hive是一个SQL解析引擎,将SQL语句转译成MR Job,然后再在Hadoop平台上运行,达到快速开发的目的 Hive中的表是纯逻辑表,就只是表的定义,即表的元数据。本质就是Hadoop的目...

霉男纸
今天
5
0
二、Spring Cloud—Eureka(Greenwich.SR1)

注:本系列文章所用工具及版本如下:开发工具(IDEA 2018.3.5),Spring Boot(2.1.3.RELEASE),Spring Cloud(Greenwich.SR1),Maven(3.6.0),JDK(1.8) Eureka: Eureka是Netflix开发...

倪伟伟
昨天
15
0
eclipse常用插件

amaterasUML https://takezoe.github.io/amateras-update-site/ https://github.com/takezoe/amateras-modeler modelGoon https://www.cnblogs.com/aademeng/articles/6890266.html......

大头鬼_yc
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部