`
Fred_Han
  • 浏览: 148164 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用iBatis的类型处理器TypeHandlerCallback(转)

    博客分类:
  • WEB
 
阅读更多

iBatis的扩展组件主要有TypeHandlerCallback、CacheController、 DataSourceFactory、TransactionConfig。其中TypeHandlerCallback可以实现自定义的类型处理逻辑, 以便处理非标准数据库、驱动程序和(或)数据类型。

 

场景举例

有如下数据表,请注意字段status的类型及含义:

 

Sql代码  收藏代码
  1. CREATE   DATABASE  ibatis;  
  2. USE test_ibatis;  
  3. CREATE   TABLE  person  
  4. (  
  5.    id INT   NOT   NULL  AUTO_INCREMENT,  
  6.    name   VARCHAR (20)  NOT   NULL  comment  '姓名' ,  
  7.    status TINYINT NOT   NULL  comment  '状态(1可用,-1不可用,0默认)' ,  
  8.    PRIMARY   KEY  (id)  
  9. )  
  10. ENGINE=InnoDB  
  11. DEFAULT   CHARACTER   SET =utf8;  

 

对应的实体模型类里将status定义为枚举型,如:

 

Java代码  收藏代码
  1. public   class  Person {  
  2.   
  3.     private   int  id;  
  4.     private  String name;  
  5.     private  Status status;  // 注意这里   
  6.   
  7.     // getters and setters...   
  8. }  

 

注:如果将status定义为整型,虽然与表中的字段类型一致了,但在赋值时setStatus(int status),只能传数字,不易被理解,没有人会明白应该传什么值,1或-1又代表了什么含义,且易产生脏数据,比如有意无意间会传321。

 

用枚举型给status赋值,既直观又限定范围。如:

 

Java代码  收藏代码
  1. ......  
  2. Person person = new  Person();  
  3. person.setName("yumin" );  
  4. person.setStatus(Status.AVAILABLE);; // 注意这里   
  5. boolean  result = DAO.insert(person);  
  6. .......  

 

代码里出现的枚举型Status,可以这样进行定义:

 

Java代码  收藏代码
  1. public   enum  Status {  
  2.     // 默认0, 可用1, 不可用-1   
  3.     DEFAULT(0 ), AVAILABLE( 1 ), UNAVAILABLE(- 1 );  
  4. }  

 

但按上述做法执行写入操作时,发生了如下异常:

 

Java代码  收藏代码
  1. Caused by: java.sql.SQLException:   
  2. Incorrect integer value: 'AVAILABLE'   for  column  'status'  at row  1   

 

类型不匹配,AVAILABLE用在了整型字段status。

 

异常出现的症结在于, 数据表里的字段是用整型存储这没问题, 但Java代码里应该用枚举型会更友好, 两者间在数据类型上就存在一定的矛盾, 即"javaType=enum"而"jdbcType=integer" 。这时就需用到TypeHandlerCallback,通过实现该接口来处理中间的转换。

 

题外话:还有一种做法,定义Person类时,定义两个status,第一个status为整型,但取消setStatus方法,只负责在数据表存 储时用,另一个叫status2为枚举型,负责与外部交互,赋值时只能用status2,内部将status2转换为status,这样既能保证友好又能 通过转换保持类型的一致。但暂时让我们看看若通过iBatis的扩展应该如何实现。

 

实例演示

TypeHandlerCallback接口,下面是它的源代码:

 

Java代码  收藏代码
  1. public   abstract   interface  TypeHandlerCallback {  
  2.   
  3.       public   abstract   void  setParameter(ParameterSetter setter, Object object)   
  4. throws  SQLException;  
  5.   
  6.       public   abstract  Object getResult(ResultGetter getter)  throws  SQLException;  
  7.   
  8.       public   abstract  Object valueOf(String string);  
  9. }  

 

接下来我们一起Step-by-step操作 ——

 

第一步:基于TypeHandlerCallback实现类

 

Java代码  收藏代码
  1. /**  
  2.  *   
  3.  */   
  4. package  me.yumin.java.ibatis.handler;  
  5.   
  6. import  com.ibatis.sqlmap.client.extensions.ParameterSetter;  
  7. import  com.ibatis.sqlmap.client.extensions.ResultGetter;  
  8. import  com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;  
  9. import  java.sql.SQLException;  
  10. import  java.sql.Types;  
  11. import  me.yumin.java.ibatis.enumtype.Status;  
  12.   
  13. /**  
  14.  * @author yumin  
  15.  *   
  16.  */   
  17. public   class  StatusHandler  implements  TypeHandlerCallback {  
  18.   
  19.     @Override   
  20.     public   void  setParameter(ParameterSetter setter, Object parameter)   
  21. throws  SQLException {  
  22.   
  23.         /*  
  24.          * 在sqlMap中配parameterMap的属性typeHandler  
  25.          * 和sqlMapConfig中配全局typeHandler时才会触发  
  26.          */   
  27.         if  ( null  == parameter) {  
  28.             setter.setNull(Types.INTEGER); // 若没有传值则null,表字段不允许则异常   
  29.         } else  {  
  30.             setter.setInt(((Status) parameter).getValue());  
  31.         }  
  32.     }  
  33.   
  34.     @Override   
  35.     public  Object getResult(ResultGetter getter)  throws  SQLException {  
  36.   
  37.         /*  
  38.          * 仅在sqlMap中配置resultMap的属性typeHandler  
  39.          * 和在sqlMapConfig中配全局typeHandler才会触发  
  40.          */   
  41.         Object result = null ;  
  42.   
  43.         //if (!getter.wasNull() && null != getter.getObject()) {    
  44.         // 上面有问题,修复如下.wasNull是判断前一个字段是否为null   
  45.         if  ( null  != getter.getObject()) {  
  46.             result = getStatus(getter.getInt());  
  47.         }  
  48.   
  49.         return  result;  
  50.     }  
  51.   
  52.     @Override   
  53.     public  Object valueOf(String string) {  
  54.   
  55.         /*  
  56.          * 处理属性或参数为null情况  
  57.          * 入参即为配置项nullValue  
  58.          */   
  59.         Object result = null ;  
  60.         int  integer =  0 ;  
  61.   
  62.         if  ( null  != string &&  0  < string.length()) {  
  63.             try  {  
  64.                 integer = Integer.parseInt(string);  
  65.             } catch  (NumberFormatException e) {  
  66.                 e.printStackTrace();  
  67.             }  
  68.         }  
  69.         result = getStatus(integer);  
  70.   
  71.         return  result;  
  72.     }  
  73.   
  74.     /**  
  75.      *   
  76.      * @param value  
  77.      * @return  
  78.      */   
  79.     private  Object getStatus( int  value) {  
  80.   
  81.         Object result = null ;  
  82.   
  83.         for  (Status status : Status.values()) {  
  84.             if  (value == status.getValue()) {  
  85.                 result = status;  
  86.                 break ;  
  87.             }  
  88.         }  
  89.   
  90.         return  result;  
  91.     }  
  92.   
  93. }  
 

第二步:在sqlMap中指定属性typeHandler

所有完整的sqlMap配置文件如下:

 

Xml代码  收藏代码
  1. <? xml   version = "1.0"   encoding = "UTF-8"   ?>   
  2. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">   
  3. < sqlMap   namespace = "Person" >   
  4.   
  5.     < typeAlias   alias = "Person"   type = "me.yumin.java.ibatis.domain.Person"   />   
  6.     < parameterMap   class = "Person"   id = "person" >   
  7.         < parameter   property = "name"   />   
  8.         < parameter   property = "status"   typeHandler = "me.yumin.java.ibatis.handler.StatusHandler"   />   
  9.         <!-- 若没有使用parameterMap且未给属性指定typeHandler  
  10.              则在给SQL传值时不会调Handler中的setParameter方法 -->   
  11.     </ parameterMap >   
  12.     < resultMap   class = "Person"   id = "person" >   
  13.         < result   property = "id"   column = "id"   />   
  14.         < result   property = "name"   column = "name"   />   
  15.         < result   property = "status"   column = "status"   typeHandler = "me.yumin.java.ibatis.handler.StatusHandler"   nullValue = "0"   />   
  16.         <!-- 同上若没用resultMap且未给属性指定typeHandler  
  17.              则在返回表数据时不会调Handler中的getResult方法 -->   
  18.     </ resultMap >   
  19.   
  20.     < insert   id = "insert"   parameterMap = "person" >   
  21.         <![CDATA[  
  22.             INSERT INTO person (name, status) VALUES (?, ?)  
  23.         ]]>   
  24.         < selectKey   keyProperty = "id"   resultClass = "java.lang.Integer" >   
  25.             SELECT LAST_INSERT_ID()  
  26.         </ selectKey >   
  27.     </ insert >   
  28.   
  29.     < select   id = "query"   parameterClass = "java.lang.Integer"   resultMap = "person" >   
  30.         <![CDATA[  
  31.             SELECT id, name, status FROM person WHERE id=#id#  
  32.         ]]>   
  33.     </ select >   
  34.   
  35. </ sqlMap >   
 

主要处理过程是,因在sqlMap中给属性配置了typeHandler,所以在写或改数据前,先调用setParameter方法,再生成SQL,这时已将枚举型转换为整型;在读取数据后映射类时,会调用getResult方法,将整型转换为枚举型。

 

完整的示例请见附件,导入到IDE即可运行, IBatisTest是测试用例。

 

上述实例满足了一开始的需求,即Java类中将属性定义为枚举型,在存储时仍用整型,既友好直观地让使用者给类赋值又满足了存储需要。应用场景还有 很多,如:对所有字符串型数据先压缩再存储,则可在sqlMapConfig中定义全局typeHandler, 凡"javaType=java.lang.String"时,都通过该扩展在写之前先压缩,读取后先解压再返回。


若将Handler定义在sqlMapConfig,则该typeHandler是全局可用的。

 

全局typeHandler定义:

 

Xml代码  收藏代码
  1. < sqlMapConfig >   
  2.     ......  
  3.     < typeHandler   javaType = "package.Type"   callback = "package.Handler"   />   
  4.     ......  
  5. </ sqlMapConfig >   

 转自http://blog.csdn.net/solo_knight/article/details/7715683

分享到:
评论

相关推荐

    使用iBatis的类型处理器TypeHandlerCallback

    `TypeHandlerCallback`是iBatis(或MyBatis)中的一个重要接口,用于处理Java类型与数据库类型之间的转换。在处理数据库操作时,数据的类型转换是必不可少的步骤,因为Java类型和数据库存储的数据类型往往不完全匹配...

    从iBatis迁移到MyBatis

    8. **类型处理器**:MyBatis的TypeHandler接口提供了更丰富的类型转换,避免了在SQL语句中处理复杂数据类型时的困扰。 9. **缓存机制**:MyBatis提供了一级缓存和二级缓存,可以提高数据查询的效率。 10. **集成...

    .net中使用iBATIS的小例子

    下面我们将详细探讨iBATIS在.NET中的使用方法,以及如何利用提供的文件进行实践。 首先,了解iBATIS的基本概念。iBATIS是一个轻量级框架,它的核心功能是动态SQL映射,允许开发者编写SQL语句并将其封装到XML配置...

    ibatis的使用教程

    要开始使用 Ibatis,首先需要从官方网站下载最新版本的 ibatis jar 包,以及 log4j 日志框架的 jar 包。然后,在Java项目中添加这些库,配置log4j.properties以开启SQL日志输出。接着,新建主配置文件sqlMapConfig....

    ibatis类型

    标题 "ibatis类型" 暗示我们讨论的是关于iBATIS这个持久层框架的一些特定类型或组件。iBATIS是Java开发中的一个流行数据库访问框架,它允许开发者将SQL语句直接集成到XML配置文件中,实现了SQL与Java代码的分离,...

    ibatis简易使用 ibatis简易使用 ibatis简易使用

    以下是对iBATIS简易使用的详细解释: 1. **环境准备**: - **jar文件**:iBATIS框架运行需要依赖一些库文件,包括`log4j`用于日志记录,`ibatis`核心库,以及`jdbc`驱动,这些都需要添加到项目的类路径中。 - **...

    iBATIS操作Oracle CLOB数据

    综上所述,通过iBATIS操作Oracle的CLOB数据,需要对iBATIS的映射文件、类型处理器以及Oracle的CLOB特性有深入理解。在实际开发中,合理配置和使用这些机制,能够有效地管理大量文本数据,同时保持代码的简洁性和可...

    ibatis 支持枚举类型

    Ibatis对枚举类型的原生支持可能不如实体类那样直观,但通过一些策略,我们可以实现枚举与数据库字段之间的映射。以下将详细解释如何在Ibatis中处理枚举类型。 首先,我们需要定义枚举类。枚举类通常包含若干枚举...

    ibatis教程 输入参数详解

    以及ibatis的概述、如何开始使用ibatis、构建SqlSessionFactory的方法(包括通过XML和不使用XML的方式)、获取SqlSession的过程、探索映射SQL语句的方法、命名空间的注意事项、作用域与生命周期的解释、mapper配置...

    ibatis 相关使用文档及安装包ibatis 相关使用文档及安装包

    这个压缩包包含了iBATIS的相关使用文档和安装包,是学习和使用iBATIS的重要参考资料。 《iBATIS-SqlMaps-2.pdf》可能是关于iBATIS SQL映射器的详细指南,它会介绍如何编写SQL Map配置文件,这些文件定义了数据库...

    ibatis demo,ibatis例子,ibatis示例

    Ibatis提供了多种方式来实现映射,如自动类型匹配、自定义类型处理器、复杂关联映射等。 7. **缓存机制**:Ibatis内置了本地缓存和二级缓存,可以提高数据读取速度。本地缓存作用于单个SqlSession,而二级缓存则...

    iBatis详细使用手册(.net版)[收集].pdf

    用户可以使用ResultMap来定义结果映射关系,以便将数据库查询结果映射到强类型数据对象中。 7.iBatis的应用场景 iBatis可以应用于各种数据访问场景,包括Web应用程序、桌面应用程序、移动应用程序等。它提供了一种...

    3、mybatis类型的定义方式

    自定义类型处理器需要实现`org.apache.ibatis.type.TypeHandler`接口,并重写`setNonNullParameter`、`getNullableResult`和`getResultFromCursor`方法。 ```java public class CustomTypeHandler implements ...

    ibatis 使用手册

    《iBatis 使用手册》是一份详尽的开发资源,涵盖了iBatis框架的各个方面,包括iBatis的开发指南、SQL Maps的使用以及入门教程。iBatis是一款优秀的持久层框架,它允许Java开发者将SQL语句与Java代码分离,实现数据...

    ibatis3资料-介绍

    5. **类型处理器扩展**:iBATIS3允许开发者自定义类型处理器,用于处理不同类型之间的转换,这为处理非标准数据类型提供了便利。 6. **插件架构**:iBATIS3支持插件架构,开发者可以通过编写插件来扩展框架的功能,...

    iBatis Web用法实例

    在这个"iBatis Web用法实例"中,我们将深入探讨如何在Web项目中集成并使用iBatis,以及相关的最佳实践。 1. **iBatis 概述**: iBatis 作为轻量级的ORM(对象关系映射)框架,它的核心思想是将SQL与Java代码分离,...

    ibatis中输入输出各种类型的参数分析及#与$区别

    ### ibatis中输入输出各种类型的参数分析及#与$区别 #### iBatis简介与特点 iBatis作为一款轻量级的Java持久层框架,以其简洁、灵活的特点,在众多框架中占据一席之地。相较于知名的Hibernate框架,iBatis在实现上...

    使用ibatis写的小项目

    **使用iBatis进行数据库操作的核心概念** iBatis是一个优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。iBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。iBatis可以被看作是一个半自动化 ...

    ibatis2小例子(转)

    标题 "ibatis2小例子(转)" 指向的是一个关于iBatis2的实战教程或示例,这是一套广泛使用的Java持久层框架,它提供了SQL映射功能,使得开发者能够方便地将数据库操作与业务逻辑相结合。在这个小例子中,可能会涉及...

    iBATIS实战

    12.2 使用自定义类型处理器 217 12.2.1 实现自定义类型处理器 217 12.2.2 创建TypeHandlerCallback 218 12.2.3 注册TypeHandlerCallback以供使用 221 12.3 使用CacheController 222 12.3.1 创建CacheController 223 ...

Global site tag (gtag.js) - Google Analytics