nighty

折腾的年华
posts - 37, comments - 143, trackbacks - 0, articles - 0

关于commons dbutils组件的一个小缺陷分析

Posted on 2011-02-12 17:33 寒武纪 阅读(2826) 评论(7)  编辑  收藏 所属分类: 数据库Java
        非常喜欢这种轻量级的JDBC封装,比起Hibernate和iBatis,可以非常自由和灵活地运用和自行二次封装,由于dbutils的BeanHandler转换方式采取了反射技术,在性能上肯定有所损失,所以项目中基本上都使用MapHandler方式来转换数据,当然就是自己写的代码多一点,也无所谓。一般的查询、子查询、联合查询、包括视图查询等等都很正常,但是发现一个比较小的问题,就是在使用聚合函数的场所,例如:select user_type, count(*) as count from `user` group by user_type这种类型查询的时候,MapHandler方式不起作用,as列都变成key为空串的K-V对,导致有许多地方使用map.get("")代码的情况出现,这种写法当然是不太好的,容易出问题。
        鉴于前面没有时间了解,就都粗略使用了上面那种粗暴的map.get("")来处理,最好的情况是让dbutils组件能自动识别到as类型的列名。于是有空了就专门看了看它的源代码,发现最主要的一段代码如下:
 1public Map<String, Object> toMap(ResultSet rs) throws SQLException {
 2        Map<String, Object> result = new CaseInsensitiveHashMap();
 3        ResultSetMetaData rsmd = rs.getMetaData();
 4        int cols = rsmd.getColumnCount();
 5
 6        for (int i = 1; i <= cols; i++{
 7            result.put(rsmd.getColumnName(i), rs.getObject(i));
 8        }

 9
10        return result;
11    }
        CaseInsensitiveHashMap是dbutils自定义的一个Map,忽略键大小写的K-V字典,但是key使用的是ResultSetMetaData.getColumnName(),我想问题大概出在这里,于是认真翻了翻java的api文档(开发做久了容易遗忘基础),果然,原来getColumnName()是:获取指定列的名称;而as关键字之后,使列名称变成用于显示的意义,这个时候应该使用getColumnLabel():获取用于打印输出和显示的指定列的建议标题。建议标题通常由 SQL AS 子句来指定。如果未指定 SQL AS,则从 getColumnLabel 返回的值将和 getColumnName 方法返回的值相同。自己手动试验了一下,果然如所料,问题就出在这里。
        所以呢,如果想要dbutils在自动转换Map及MapList时能识别聚合函数的列名,那么最好的做法就是重载这种方式,懒一点的,你就干脆修改上面那段代码,让它判断是否使用了as关键字。个人暂时搞不清楚官方为什么没有考虑这一步,有时间再思考一下!

刚进场的时候戏就落幕

Feedback

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-12 20:22 by 蒙奇奇
关注

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-13 19:30 by javafan
本来就是一个Bug,无法识别别名,低版本没问题

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-14 13:56 by retry
什么版本? 是 1.3 么?

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-14 18:08 by 寒武纪
@retry
是的,就是1.3

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-19 12:21 by jacklondon
我也用 dbutils 进行二次封装成 VelocityWeb, 也用 as , 没有发现这个 bug。 可能是因为我拦截了 map , 因为我的需求比较特别:
user_name (数据库列名) 要映射到 userName( java 属性名), 而 DBUtils 做不到,所以我拦截了重写,可能是因为这样,导致没有了这个 bug.
----------欢迎大家试用我们的单点登录 http://zhegui.biz

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2011-02-19 12:25 by jacklondon
DBUtils 1.3 的 release log 中有如下一段话,按说已经解决问题了:
BeanProcessor#mapColumnsToProperties now prefers to use column labels over column names (where aliases are not set, these should be identical) Fixes DBUTILS-57.

你这边用什么数据库?是否 JDBC 驱动有问题,需要升级?

# re: 关于commons dbutils组件的一个小缺陷分析  回复  更多评论   

2016-05-02 20:35 by starhe
dbutils中连传入到的参数都不区分大小写??

只有注册用户登录后才能发表评论。


网站导航: