摘要:背景最近在学习,在处理返回值与业务对象之间的转换非常方便,定义,标明互相之间的转换关系,即可轻松完成转换。我们会写使用原生的来获取返回值。
背景
最近在学习Mybatis,Mybatis在处理JDBC返回值与Java业务对象之间的转换非常方便,定义XML,标明互相之间的转换关系,即可轻松完成转换。
Mybatis是JDBC的封装,我们先来看看如果用原生的JDBC,如何完成ResultSet和Java业务对象之间的转换,会遇到哪些不便。
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对象转换cityPOS = new ArrayList ();
我们要完成的工作就是将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); } }缺点
转换完全和具体的业务类绑定在了一起,你如果新处理一个业务类,你得再重新写一套差不多的代码,而且随着类的属性字段的增多,你的if/else代码会越来越多,听起来是不是很恐怖。
在调用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);
这段我为了测试,是直接把对应的对象的属性名改成了数据库中的列名。
缺点因为是通过数据库的列名反射出对应的方法,而通常我们在Java中使用的是驼峰命名,怎么处理列名到对象类名的转换,这里应该有一定的代码量,当然也可以在select的时候 as成对应的属性名,这样就解决了这个问题。
我们依然需要处理类型转换。
我们可能会多选了一些列,而这个方案会统统去找反射的方法,可能会抛出异常。
结论我觉得这应该是框架会采取的方案。
总结直接用原生的JDBC完成数据库到Java业务对象的转换,肯定是非常繁琐的,从目前来看,框架应该也是用的方案2,只不过会比方案案强大的多。
从使用Mybatis这一段时间来看,其在这个方案做了这么几件事。
解决了数据库列名到Java列名的映射。
解决了数据库类型到Java类型的转换工作。
在转换过程中具备一定的容错能力。
后续后续会研究下Mybatis在这方面所做的工作和源码,有兴趣可以持续关注我的微信公众号。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/67417.html
摘要:什么是呢全称,是提出的一个对象持久化规范,各应用服务器自主选择具体实现。仅仅只是一个规范,而不是产品使用本身是不能做到持久化的。只要提供了持久化类与表的映射关系,框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。 我们在进行事务处理往往需要和数据库进行交互,这其中有关系型数据库(MySql,Sql Server,Oracle)或者是非关系型数据库(Redis,Hadhoop)...
摘要:什么是呢全称,是提出的一个对象持久化规范,各应用服务器自主选择具体实现。仅仅只是一个规范,而不是产品使用本身是不能做到持久化的。只要提供了持久化类与表的映射关系,框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。 我们在进行事务处理往往需要和数据库进行交互,这其中有关系型数据库(MySql,Sql Server,Oracle)或者是非关系型数据库(Redis,Hadhoop)...
摘要:我们对语句做适当改变,就完成了注入,因为普通的不会对做任何处理,该例中单引号后的生效,拉出了所有数据。查询资料后,发现还要开启一个参数,让端缓存,缓存是级别的。结论是个好东西。 背景 最近因为工作调整的关系,都在和数据库打交道,增加了许多和JDBC亲密接触的机会,其实我们用的是Mybatis啦。知其然,知其所以然,是我们工程师童鞋们应该追求的事情,能够帮助你更好的理解这个技术,面对问题...
阅读 1229·2021-11-24 09:39
阅读 378·2019-08-30 14:12
阅读 2591·2019-08-30 13:10
阅读 2433·2019-08-30 12:44
阅读 957·2019-08-29 16:31
阅读 845·2019-08-29 13:10
阅读 2432·2019-08-27 10:57
阅读 3152·2019-08-26 13:57