博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
小酒一杯品源码-DbUtils代码解读
阅读量:7070 次
发布时间:2019-06-28

本文共 3740 字,大约阅读时间需要 12 分钟。

hot3.png

ORM一直是Web开发一个热点话题,DbUtils则是给出了一个相当简洁的答案。DbUtils的嵌套也不深,而且主动的API调用也非常符合程序员的思维(Hibernate和iBatis这种隐藏了大多数细节的框架,连找到个入口都要费半天劲)。

话说最常用的CRUD,使用JDBC最痛的无非是将ResultSet转换为JavaBean。DbUtils则是正好命中这个要害,使用ResultSetHandler机制来解决这个问题。

之前用过Spring JDBC Template,差不多也是这个机制。DbUtils的亮点则是BeanHandler,可以无需手写转换函数,自动根据class生成一个handler。

BeanProcessor的核心代码做了几件事:

  • 提取Bean的字段信息,结果集的字段信息,并作映射;

  • 对Bean的字段做类型转换

字段映射的代码:

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);            }            String propertyName = columnToPropertyOverrides.get(columnName);            if (propertyName == null) {                propertyName = columnName;            }            for (int i = 0; i < props.length; i++) {                if (propertyName.equalsIgnoreCase(props[i].getName())) {                    columnToProperty[col] = i;                    break;                }            }        }        return columnToProperty;    }

这里ResultSetMetaDataPropertyDescriptor分别是JDBC和Bean API里获取的元信息。

对字段做类型转换的代码比较多,主要方法是callSetter

private void callSetter(Object target, PropertyDescriptor prop, Object value) throws SQLException { Method setter = prop.getWriteMethod(); if (setter == null) { return; } Class
[] params = setter.getParameterTypes(); // convert types for some popular ones if (value instanceof java.util.Date) { final String targetType = params[0].getName(); if ("java.sql.Date".equals(targetType)) { value = new java.sql.Date(((java.util.Date) value).getTime()); } else if ("java.sql.Time".equals(targetType)) { value = new java.sql.Time(((java.util.Date) value).getTime()); } else if ("java.sql.Timestamp".equals(targetType)) { value = new java.sql.Timestamp(((java.util.Date) value).getTime()); } } // 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, cannot convert " + value.getClass().getName() + " to " + params[0].getName()); // value cannot be null here because isCompatibleType allows null }}

这里省略了一些异常的捕获。this.isCompatibleType方法里有一些关于基本类型和装箱类型的转换。

private boolean isCompatibleType(Object value, Class
type) { // Do object check first, then primitives if (value == null || type.isInstance(value)) { return true; } else if (type.equals(Integer.TYPE) && value instanceof Integer) { return true; } else if (type.equals(Long.TYPE) && value instanceof Long) { return true; } else if (type.equals(Double.TYPE) && value instanceof Double) { return true; } else if (type.equals(Float.TYPE) && value instanceof Float) { return true; } else if (type.equals(Short.TYPE) && value instanceof Short) { return true; } else if (type.equals(Byte.TYPE) && value instanceof Byte) { return true; } else if (type.equals(Character.TYPE) && value instanceof Character) { return true; } else if (type.equals(Boolean.TYPE) && value instanceof Boolean) { return true; } return false;}

至此,一个ResultSet至Bean的转换就完成了,还是相当简洁的。

转载于:https://my.oschina.net/flashsword/blog/160498

你可能感兴趣的文章
服务器虚拟化技术为企业带来的便利
查看>>
【Android studio】CMakeLists
查看>>
salt 常用模块介绍
查看>>
多cpu 多核cpu 多芯 超线程
查看>>
源码包安装vmtools
查看>>
The server encountered an internal error () that prevented it from fulfilling this request.
查看>>
是时候抛弃Eclipse转向IntelliJ了
查看>>
我的友情链接
查看>>
Android开发学习笔记:浅谈WebView
查看>>
设计模式之------命令链模式
查看>>
DNS解析服务器
查看>>
unable kill namenode hadoop3.0.3 解决到放弃解决的过程
查看>>
解决软件提示unable to find a version of runtime to
查看>>
加载一个GIF图片在视图里
查看>>
Workman websocket 握手连接
查看>>
es6中新增对象的特性和方法
查看>>
收集2012集群共享卷空间使用情况,并用邮件通知管理员
查看>>
varnish之ban.url无效的一种情况
查看>>
电话诈骗之思考|安全是什么?
查看>>
linux数据恢复
查看>>