- 浏览: 157409 次
- 性别:
- 来自: 无锡
文章分类
最新评论
-
lgh1992314:
1.7<pre name="code" ...
Commons DbUtils 源码阅读四 -
lgh1992314:
it was too slow to call the met ...
Commons DbUtils 源码阅读四 -
lgh1992314:
toBeanList的存在位置有点变态
Commons DbUtils 源码阅读二 -
lgh1992314:
toBeanList的存在位置有点变态
Commons DbUtils 源码阅读二 -
hwwjason:
<target name="jar" ...
Apache Ant 实例介绍
在读BasicRowProcessor 类时,它有两个方法(toBean和toBeanList)都将最终的处理工作交给了BeanProcessor,所以,今天来拜读一下此类, 在读此类的时候,决定换个方式,就一个方法慢慢的展开分析,这样或许也会更有趣味和吸引力吧:
public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException { PropertyDescriptor[] props = this.propertyDescriptors(type);// 1)获取指定类的属性描述对象集合 ResultSetMetaData rsmd = rs.getMetaData(); int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);//2)列名转换为bean属性 return this.createBean(rs, type, props, columnToProperty);//3) }
这个方法呢,是将ResultSet的指定行创建一个指定类型的Bean实例返回:
1) 这个是利用内省机制,获取指定类的属性描述数组,来看看这个propertyDescriptors方法
private PropertyDescriptor[] propertyDescriptors(Class<?> c) throws SQLException { // Introspector caches BeanInfo classes for better performance BeanInfo beanInfo = null; try { beanInfo = Introspector.getBeanInfo(c); } catch (IntrospectionException e) { throw new SQLException("Bean introspection failed: " + e.getMessage()); } return beanInfo.getPropertyDescriptors(); }
通过Introspector的静态方法getBeanInfo,获取指定类型的BeanInfo实例,再调用getPropertyDescriptors()方法返回该类的所有PropertyDescriptor数组,非常的简洁明了,这个就是传说中的内省了
2) 这个方法的功能呢,是将column数组与类的properties匹配,两个都是数组,然后返回还是个数组,居然还map名,所以,看看里面是如何实现的:
protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, PropertyDescriptor[] props) throws SQLException { int cols = rsmd.getColumnCount(); int columnToProperty[] = new int[cols + 1]; Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND); for (int col = 1; col <= cols; col++) { String columnName = rsmd.getColumnLabel(col);//获取列名 if (null == columnName || 0 == columnName.length()) { columnName = rsmd.getColumnName(col); } for (int i = 0; i < props.length; i++) { if (columnName.equalsIgnoreCase(props[i].getName())) {//与属性名进行匹配 columnToProperty[col] = i; break; } } } // comlumnToProperty 里面返回的是column下标对应的PropertyDescriptor属性的下标值 return columnToProperty; }
这个方法的所做的工作实际上是这样的,将ResultSet中的列名与Bean的属性进行匹配,声明的数组的长度是以ResultSet中的列数量来确定的,所以下标从1开始,然后与Bean的PropertyDescriptor数组进行属性名匹配,如果有找到,则在对应的列名下标数组里存入bean属性的位置。这样一来,我们就可以清晰的知道,ResultSet列名对应的Bean属性了。
OK,也许你现在看这段话有些稀里糊涂,你只要记住,这个返回的数组是按照ResultSet的列标匹配bean属性数组对应的位置的。
3)看关键方法
private <T> T createBean(ResultSet rs, Class<T> type, PropertyDescriptor[] props, int[] columnToProperty) throws SQLException { T bean = this.newInstance(type);//创建该类实例 //循环列名与bean属性匹配情况数组 for (int i = 1; i < columnToProperty.length; i++) { if (columnToProperty[i] == PROPERTY_NOT_FOUND) {//该下标没有匹配的属性,则不做处理 continue; } PropertyDescriptor prop = props[columnToProperty[i]];//获取对应属性的描述对象 Class<?> propType = prop.getPropertyType();//获取类型 Object value = this.processColumn(rs, i, propType);//获取rs对应的值 if (propType != null && value == null && propType.isPrimitive()) { value = primitiveDefaults.get(propType);//为空,获取默认值 } this.callSetter(bean, prop, value);//调用属性的setter方法 } return bean; }
这个方法呢,首先来生成一个指定类型的实例,然后循环之前处理ResultSet列名与Bean属性名匹配情况的数组,获取Bean属性特定的PropertyDescriptor实例,通过this.processColumn(rs, i, propType)这个方法获取数据库中对应的值,再调用callSetter(...)方法来为新建Bean实例赋值上值,来看看它是怎么实现的:
Method setter = prop.getWriteMethod();//通过PropertyDescriptor获取对应属性的Setter方法
然后匹配数据库类型与Bean方法的类型,如果不匹配,则抛出异常,否则通过反射来为Bean对象填入对应的值,来看具体实现:
Class<?>[] params = setter.getParameterTypes();//参数类型列表 ............................................................................ // Don't call setter if the value object isn't the right type if (this.isCompatibleType(value, params[0])) { setter.invoke(target, new Object[] { value }); } else { throw new SQLException( "Cannot set " + prop.getName() + ": incompatible types."); }
我们深刻的分析了一下toBean方法,toBeanList方法呢,实际上就是循环ResultSet,获取每一行,然后交由toBean()方法处理,贴出具体的代码:
public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException { List<T> results = new ArrayList<T>(); if (!rs.next()) { return results; } PropertyDescriptor[] props = this.propertyDescriptors(type); ResultSetMetaData rsmd = rs.getMetaData(); int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); do { results.add(this.createBean(rs, type, props, columnToProperty)); } while (rs.next()); return results; }
这个方法,我没有搞明白为什么不直接循环调用toBean()方法,直接调用toBean()方法不好嘛?!(或许是我资力尚浅,没有明白作者的意图)
这里也贴出个人认为可以完善的这个方法实现吧
// PropertyDescriptor[] props = this.propertyDescriptors(type); // ResultSetMetaData rsmd = rs.getMetaData(); // int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); do { // results.add(this.createBean(rs, type, props, columnToProperty)); results.add(this.toBean(rs, type));//修改部分 } while (rs.next());
如果有朋友认为我这样写不对,还请不吝教导。
评论
public <T> List<T> toBeanList(ResultSet rs, Class<T> type) throws SQLException { List<T> results = new ArrayList<T>(); if (!rs.next()) { return results; } PropertyDescriptor[] props = this.propertyDescriptors(type); ResultSetMetaData rsmd = rs.getMetaData(); int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); do { results.add(this.createBean(rs, type, props, columnToProperty)); } while (rs.next()); return results; }
That’s also why there is a toBeanList method in the RowProcessor interface.
是因为会多次调用原本只需调用一次的 propertyDescriptors(type)方法 和 mapColumnsToProperties(rsmd, props)方法
PropertyDescriptor[] props = this.propertyDescriptors(type);
ResultSetMetaData rsmd = rs.getMetaData();
int[] columnToProperty = this.mapColumnsToProperties(rsmd, props)
做这些事情, 有点浪费
发表评论
-
Spring SpringMVC MyBatis MVN
2011-11-23 22:29 0突然想起用maven了,虽然早在今年上半年就有买了本书在看 ... -
Apache Lucene3.0 入门实例介绍
2011-05-24 23:02 1878咱这搞技术活儿的吧 ... -
Commons Logging 源码解析二
2011-05-18 22:52 0我们说过,Commons Loggi ... -
Commons Logging 源码解析一
2011-05-15 22:43 2079最近一段日子可真是够忙的,项目上线终于开始有回报了!一直要 ... -
Commons FileUpload 源码解析二
2011-04-14 23:03 0FileItemFactory: /** * ... -
Commons FileUpload 源码解析一
2011-04-14 20:39 0Commons FileUpload?! 哇噢~可以这样说 ... -
JExcelAPI(jxl)读写Excel应用
2011-04-04 23:51 10244这篇博文在我的草 ... -
Apache Axis 服务创建
2011-03-11 23:38 2302在Apache Axis了解一文中,已经对Apache A ... -
Apache Axis了解
2011-03-04 22:16 1503最近项目到了最最关键的时刻了,客户的试用期也快结束了,客户 ... -
Commons DbUtils源码阅读之实例及测试应用
2011-02-23 22:39 1933去年整了一Commons DbUtils的源码阅读,现如今 ... -
Apache Ant常用标签介绍
2011-02-20 22:24 4808在上一篇博文中简单介绍了一下Ant是如何编译和发布Java ... -
Apache Ant 实例介绍
2011-02-17 22:55 4466开开心心的过了个年,快快乐乐的过了个情人节!So,继续我技 ... -
Commons DbUtils 源码阅读八
2011-01-19 21:39 1845距离DbUtils组件源码七 ... -
Commons DbUtils 源码阅读七
2011-01-03 13:36 2079实际上,我们也知道官网上对ResultSet的解析示例: ... -
Commons DbUtils 源码阅读六
2010-12-24 23:27 1708DbUtils组件的核心部分已经解析完了,实际上呢,DbUt ... -
Commons DbUtils 源码阅读五
2010-12-13 21:31 5850关于DbUtils,我们深入剖析了对ResultSet解析 ... -
Commons DbUtils 源码阅读三
2010-11-29 22:26 3085前两天着实被javaeye关闭着急了一下,还好,总算开放了 ... -
Commons DbUtils 源码阅读二
2010-11-19 21:17 1909DbUtils组件的整个代码结构做了一个简单的疏导,现在来 ... -
Commons DbUtils 源码阅读一
2010-11-17 22:51 2967想起读源码了! 主要是出于这几个方面的考虑: ...
相关推荐
DbUtils源码的阅读可以从以下几个方面入手: 1. **QueryRunner**:查看QueryRunner类的源码,理解其如何处理SQL查询和更新操作,以及如何处理异常。 2. **ResultSetHandler**:研究不同的结果集处理器实现,了解...
赠送源代码:commons-dbutils-1.7-sources.jar; 赠送Maven依赖信息文件:commons-dbutils-1.7.pom; 包含翻译后的API文档:commons-dbutils-1.7-javadoc-API文档-中文(简体)版.zip; Maven坐标:commons-dbutils:...
commons-dbutils包是Apache开源组织提供的用于操作数据库的工具包。简单来讲,这个工具包就是用来更加方便我们操作数据库的,最近工作中使用了一下,感觉确实方便很多,基本告别自己封装JDBC代码对数据库进行增删改...
`commons-dbutils-1.6-sources.jar`包含了源代码,这对于开发者来说是极其宝贵的资源,因为可以方便地查看和理解DBUtils内部的工作机制,进行调试或自定义扩展。 DBUtils的设计原则是简单、高效和健壮。它不是ORM...
使用 Commons dbutils 可以极大地简化 JDBC 编程,避免了许多手动处理连接、声明和结果集的工作,同时也提高了代码的可读性和可维护性。例如,使用 `QueryRunner` 执行查询和更新操作时,只需要提供 SQL 语句、参数...
赠送源代码:commons-dbutils-1.7-sources.jar; 赠送Maven依赖信息文件:commons-dbutils-1.7.pom; 包含翻译后的API文档:commons-dbutils-1.7-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:commons-...
这是DBUtils的源码版本,开发者可以查看并学习源代码,理解其内部实现逻辑,进行调试或定制功能。源码中包含了详细的注释,有助于理解每个方法的作用和用法。 3. 关于DBUtils的知识点: - **数据库连接管理**:...
而"commons-dbutils-1.3-src.zip"则包含了源代码,对于开发者来说,查看源码有助于理解其工作原理,进行定制或扩展。 在实际使用中,开发者可以通过以下步骤集成DBUtils: 1. 添加DBUtils的jar文件到项目的类路径...
通过阅读和分析"commons-dbutils-1.7-src.zip"中的源代码,开发者可以深入理解DBUtils如何实现这些功能,如何优化JDBC操作,以及如何在自己的项目中更好地利用这个框架。同时,源代码也可以作为学习Java编程和数据库...
Apache Commons DBUtils是一个Java库,它为JDBC(Java Database Connectivity)提供了一个实用工具层,旨在简化数据库操作,减轻开发...在实际项目中,结合合适的数据源,DBUtils能够有效地提升代码质量和可维护性。
通过 Apache Commons DBUtils,我们可以方便地执行 SQL 语句并处理结果,避免了手动处理数据库连接和结果集带来的繁琐工作,提高了代码的可读性和可维护性。同时,由于 DBUtils 内部对异常进行了处理和包装,使得...
commons-dbutils-1.6的jar包、源码、文档说明.zip
通过 `commons-dbutils-master` 压缩包,你可以获取到 DbUtils 的源代码,深入理解其实现原理,并根据项目需求进行自定义扩展。总的来说,Apache Commons DbUtils 是一个值得信赖的工具,它让 JDBC 编程变得更加简洁...
总的来说,Apache Commons DBUtils是Java开发中一个不可或缺的工具,它极大地简化了数据库操作,提升了代码的可读性和可维护性,同时降低了出错的可能性。对于初学者和经验丰富的开发者来说,理解和掌握DBUtils都是...
这个"commons-dbutils-1.0-src.zip"文件包含了DBUtils 1.0版本的源代码,使得开发者能够深入理解其内部机制,进行定制化开发或者调试。DBUtils库主要为JDBC(Java Database Connectivity)提供了一层方便、高效的...
源码分析方面,你可以通过阅读DBUtils的源代码来了解其内部机制,比如: - 如何封装JDBC异常,创建自定义的异常类。 - `QueryRunner`如何处理SQL查询和更新,以及如何处理结果集。 - 批处理的实现原理,包括如何...
DbUtils与JDBC结合使用,可以避免大量重复的数据库连接关闭、异常处理等代码,使数据库操作更加简洁、安全。DbUtils的核心类有QueryRunner、ResultSetHandler等,它们简化了常见的CRUD操作,比如执行SQL查询、更新、...
在解压并使用“commons-dbutils-1.4(用于连接池)C3P0.rar”中的文件时,首先需要将C3P0的配置文件(如c3p0-config.xml)配置到项目中,并在代码中导入DBUtils和C3P0的相关依赖。然后,可以通过DBUtils的Query...
apache-commons下全部官方源码和官方API文档,其中有: commons-beanutils-1.8.0 commons-codec commons-collections commons-dbcp commons-dbutils commons-fileupload commons-io commons-lang commons-lang3 ...
`commons-dbutils-1.4-src.zip` 则提供了源代码,开发者可以深入研究其内部实现,了解每个类和方法的工作原理,这对于学习和调试很有帮助。 通过源码,我们可以看到 QueryRunner 如何优化 SQL 执行,如何处理结果集...