Ibatis的类型处理器TypeHandler解析
Ibatis允许用户像在hibernate中一样定义自己的类型,但是,用户自定义类型需要与数据库中的字段类型进行对应。它的处理方法是允许我们扩展TypeHandler。Ibatis框架在处理该数据类型时就会自动调用TypeHandler进行类型转换,非常方便,ibatis中所有的类型都有它自己的TypeHandler,只是一些常用的数据类类型它已经给我们实现了而已。
在配置文件中,我们有两个地方可以配置这种处理器。
第一个地方是sqlMap文件中标签ResultMap或者ParameterMap中的TypeHandler属性,这里配置的handler是局部属性,只会在该ResultMap中才会进行转换。
<resultMap id="UserOrder" class="UserOrderDO" groupBy="id">......<result property="tripType" column="trip_Type"typeHandler="com.taobao.et.biz.dal.common.EnumTypeHandlerCallBack"/>...... </resultMap>
第二个地方是sqlMapConfig文件中的标签typeHandlers中配置typeHandle子标签,这里配置的标签是全局属性,任何只要匹配该子标签的地方都会自动使用该Handler.
<typeHandlers> <typeHandler jdbcType="CLOB" javaType="java.lang.String" callback="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/> </typeHandlers>
例如这里的全局配置,如果此时某个数据库字段的jdbcType是CLOB类型,并且映射的JavaType类型是字符串类型,那么就会自动调用这里的callback来实行类型转换。
那么Ibatis是如何确定使用哪一个TypeHandler的呢?!
它会在自己的局部区域寻找是否在配置文件中配置了Handler,找到了就使用这个handler,如果没有找到,就会查找是否有全局handler,也就是第二种方式配置的handler,这里要注意,可能我们也没有在全局配置文件中配置handler,此时,Ibatis就会根据实际类型配置默认的handler。
我们来看一些关键代码,按照查找步骤,这里我去掉了异常,只看关键的部分。
第一步:从局部Reultmap中取出配置属性。
String propertyName = childAttributes.getProperty("property");String nullValue = childAttributes.getProperty("nullValue");String jdbcType = childAttributes.getProperty("jdbcType");String javaType = childAttributes.getProperty("javaType");String columnName = childAttributes.getProperty("column");String columnIndex = childAttributes.getProperty("columnIndex");String statementName = childAttributes.getProperty("select");String resultMapName = childAttributes.getProperty("resultMap");String callback = childAttributes.getProperty("typeHandler");callback = vars.typeHandlerFactory.resolveAlias(callback);javaType = vars.typeHandlerFactory.resolveAlias(javaType);TypeHandler handler = null;if (callback != null) { // 注意这里,如果配置了就使用这个配置的handlerObject impl = Resources.classForName(callback).newInstance();if (impl instanceof TypeHandlerCallback) {handler = new CustomTypeHandler((TypeHandlerCallback) impl);} else if (impl instanceof TypeHandler) {handler = (TypeHandler) impl;} else {throw new NestedRuntimeException ("The class '' is not a valid implementation of TypeHandler or TypeHandlerCallback");}} else {//如果没有配置,就到这里来找handler = resolveTypeHandler(vars.client.getDelegate().getTypeHandlerFactory(), vars.currentResultMap.getResultClass(), propertyName, javaType, jdbcType, true);}
第二步,如果局部配置中没有找到,就到下面去找。
public TypeHandler resolveTypeHandler(TypeHandlerFactory typeHandlerFactory, Class clazz, String propertyName, String javaType, String jdbcType, boolean useSetterToResolve) {TypeHandler handler = null;if (clazz == null) {// Unknownhandler = typeHandlerFactory.getUnkownTypeHandler();} else if (DomTypeMarker.class.isAssignableFrom(clazz)) {// DOMhandler = typeHandlerFactory.getTypeHandler(String.class, jdbcType);} else if (java.util.Map.class.isAssignableFrom(clazz)) {// Mapif (javaType == null) {handler = typeHandlerFactory.getUnkownTypeHandler(); //BUG 1012591 - typeHandlerFactory.getTypeHandler(java.lang.Object.class, jdbcType);} else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error. Could not set TypeHandler. Cause: " + e, e);}}} else if (typeHandlerFactory.getTypeHandler(clazz, jdbcType) != null) {// Primitivehandler = typeHandlerFactory.getTypeHandler(clazz, jdbcType);} else {// JavaBeanif (javaType == null) {if (useSetterToResolve) {Class type = PROBE.getPropertyTypeForSetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);} else {Class type = PROBE.getPropertyTypeForGetter(clazz, propertyName);handler = typeHandlerFactory.getTypeHandler(type, jdbcType);}} else {try {Class javaClass = Resources.classForName(javaType);handler = typeHandlerFactory.getTypeHandler(javaClass, jdbcType);} catch (Exception e) {throw new NestedRuntimeException("Error. Could not set TypeHandler. Cause: " + e, e);}}}return handler;}
- 相信大家已经很明白了,其实要找一个Handler,主要就是需要javaType和jdbcType,而这两个参数要么通过反射得到,要么通过配置文件中得到。因此,为了明确我们一般都在配置文件中进行申明。
- 最后来看一点 typeHandlerFactory.getTypeHandler(clazz, jdbcType)是怎么实现的。
public TypeHandler getTypeHandler(Class type, String jdbcType) {Map jdbcHandlerMap = (Map) typeHandlerMap.get(type);//首先根据JAVA类型TypeHandler handler = null;if (jdbcHandlerMap != null) {handler = (TypeHandler) jdbcHandlerMap.get(jdbcType);//每个JDBC类型if (handler == null) {handler = (TypeHandler) jdbcHandlerMap.get(null);}}return handler;}
其实一个Handler=javaType+jdbcType 。
Ibatis的类型处理器TypeHandler解析相关推荐
- MyBatis自定义类型处理器 TypeHandler
在项目开发中经常会遇到一个问题: 当我们在javabean中自定义了枚举类型或者其它某个类型,但是在数据库中存储时往往需要转换成数据库对应的类型,并且在从数据库中取出来时也需要将数据库类型转换为jav ...
- Mybatis——类型处理器TypeHandler
在日常开发中使用mybatis时,mybatis的mapper.xml.mapper接口.entity实体一般会由mybatis-generator自动生成,其中实体的每个属性与数据库表的列一一对应, ...
- 【Mybatis】类型处理器TypeHandler的作用与自定义
一.什么是类型处理器 1.类型处理器(TypeHandler) MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时,都会用类型处理器将获取到的值以合 ...
- 类型处理器TypeHandler
作用:用于JavaType和JdbcType之间的转换 解析:当Mybatis将一个Java对象写入数据库时,它会创建一个PreparedStatument对象,并且使用setValue()方法对占位 ...
- MyBatis(九):MyBatis类型处理器(TypeHandler)详解
TypeHandler简介 TypeHandler,顾名思义类型转换器,就是将数据库中的类型与Java中的类型进行相互转换的处理器. MyBatis 在设置预处理语句(PreparedStatemen ...
- MyBatis-Plus——字段类型处理器TypeHandler
字段类型处理器(TypeHandler) 1,准备工作 (1)MyBatis 中的 TypeHandler 类型处理器用于 JavaType 与 JdbcType 之间的转换,假设我们用户表中有一个联 ...
- MyBatis核心源码剖析(SqlSession XML解析 Mapper executor SQL执行过程 自定义类型处理器 缓存 日志)
MyBatis核心源码剖析 MyBatis核心源码剖析 1 MyBatis源码概述 1.1 为什么要看MyBatis框架的源码 1.2 如何深入学习MyBatis源码 1.3 源码分析的5大原则 2 ...
- mybatis TypeHandler 类型处理器
目录 1. 自定义日期类型处理器 2. 配置自定义日期处理器 3. 新增,查询 1. 自定义日期类型处理器 继承mybatis提供的BaseTypeHandler覆写方法, 来转换Java和数据库中的 ...
- MyBatis自定义类型处理器(typeHandler)
MyBatis自定义类型处理器(typeHandler) 我们执行sql语句通过PreparedStatement语句实现,PreparedStatement会设置?值,类型处理器帮PreparedS ...
最新文章
- php pdf 文字水印图片,php pdf添加水印(中文水印,图片水印)
- asp.net控件本质
- 005_Maven POM
- 基于PSO算法的带时间窗的车辆路径问题的仿真
- 6 redhat 查看rtc时间_Linux EasyStack-Redhat安装Docker
- 51单片机程序下载、ISP及串口基础知识
- 转:Python: threading.local是全局变量但是它的值却在当前调用它的线程当中
- parse 日期_日期parse()方法以及JavaScript中的示例
- Mysql 远程自动化备份
- 爬虫基本知识(转载)
- 常见的新算法的标准测试函数
- Qt学习(一)ui界面的设计
- css3动画: 3d照片旋转transfrom
- [ctf.show.reverse] 数学不及格
- 网站的工作原理:网络开发新手(或任何人)入门
- springboot下载网络图片到本地及Linux服务器(超详细)
- Java设计一个测桃花模块_20145209刘一阳《JAVA程序设计》第十五周补充测试
- 去水印小程序源码【2021年8月更新】
- 如何修改安卓日志缓冲区大小?
- APP在线抢答解决方案(RTC直播间抢答或者抢背唱歌)