关于mybatis的typehandler类的创建以及配置

来源:互联网 发布:小牛数据恢复破解版 编辑:程序博客网 时间:2024/05/16 01:08

     在最近的学习中遇到TypeHandler这个接口,它是在org.apache.ibatis.type这个包下,实现这个接口的类,配置好之后可以默认的将数据库中对应的格式转化成Java中相应的格式,简单的来说就是一个格式转换器。正如百度百科中介绍的,MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。关于mybatis的更多的信息,请查看此博客的另一篇文章。


   每当MyBatis 设置参数到PreparedStatement 或者从ResultSet 结果集中取得值时,就会使用TypeHandler 来处理数据库类型与java 类型之间转换。在MyBatis中默认设置了很多TypeHandlers,比如BooleanTypeHandler转换jdbc任何兼容的BOOLEAN成java类型Boolean, boolean 常用的还有DateTypeHandler,转换jdbc的TIMESTAMP到Java的java.sql.Date


   在MyBatis的用户指南中,有这么一段:

 

   您能够重写类型处理器(type handlers),或者创建您自己的类型处理器去处理没有被支持的或非标准的类型。要做到这一点,只要实现TypeHandler 接口(org.mybatis.type),并且将您的TypeHandler 类映射到java 类型和可选的   JDBC 类型即可。例如:// ExampleTypeHandler.javapublic class ExampleTypeHandler implements TypeHandler {   public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)       throws SQLException {       ps.setString(i, (String) parameter);   }   public Object getResult(ResultSet rs, String columnName)       throws SQLException {       return rs.getString(columnName);   }   public Object getResult(CallableStatement cs, int columnIndex)       throws SQLException {       return cs.getString(columnIndex);   }}<pre name="code" class="html">// MapperConfig.xml<typeHandlers><typeHandler javaType="String" jdbcType="VARCHAR"handler="org.mybatis.example.ExampleTypeHandler"/></typeHandlers>

使用上面的TypeHandler 将会重写已经存在的用来处理java 的String 属性、VARCHAR 参数和结果集的类型处理器。注意,MyBatis 并不会通过数据库的元数据来确认类型,所以您必须指定它的一个类型处理器,用于将VARCHAR 字段的参数和结果映射到正确的类型上。这是因为
MyBatis 在语句的执行之前都不知道它要处理的数据类型是什么。

但是在实际的操作中有些不一样,在实现接口的时候是4个方法,上述的代码中还少了一个方法,方法如下。个人理解,这里面的getResult方法是从数据库中拿值的时候进行的转化,而setParameter函数则是存值的时候需要用到的。下面的方法与上面的那个getResult方法很像,只是一个columnName参数不一样,只是简单的重载。

public Object getResult(ResultSet rs, int columnName)       throws SQLException {       return rs.getString(columnName);   }
还有关于配置的时候经常出现找不到类的情况,所以建议在配置路径之后按住Ctrl键鼠标放在路径上面看看路径是否能找到,这也是一个常用的实用小技巧。

   之后自己自定义了一个HotelTypeHandler。

   在代码中涉及到一个枚举类,即HotelTypeEnum,其代码如下

package hotel.Enum;public enum HotelTypeEnum {CHAIN("CHAIN","连锁酒店"),SUPERHOTEL("SUPERHOTEL","高级酒店");private String title;private String value;private  HotelTypeEnum(String title,String value){//枚举的构造就只能是私有的防止外部修改this.title = title;this.value = value;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}}






实现了了TypeHandler接口的类,代码如下

import java.sql.CallableStatement;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.apache.ibatis.type.JdbcType;import org.apache.ibatis.type.TypeHandler;import com.hotel.enmu.HotelTypeEnum;public class HotelTypeHander implements TypeHandler<HotelTypeEnum>{@Overridepublic HotelTypeEnum getResult(ResultSet arg0, String arg1)throws SQLException {return HotelTypeEnum.valueOf(arg0.getString(arg1));}@Overridepublic HotelTypeEnum getResult(ResultSet arg0, int arg1) throws SQLException {return HotelTypeEnum.valueOf(arg0.getString(arg1));}@Overridepublic HotelTypeEnum getResult(CallableStatement arg0, int arg1)throws SQLException {// TODO Auto-generated method stubreturn null;}@Overridepublic void setParameter(PreparedStatement arg0, int arg1,HotelTypeEnum arg2, JdbcType arg3) throws SQLException {// TODO Auto-generated method stub}}

然后在MyBatis配置文件中加上

<pre name="code" class="html"><typeHandlers>        <typeHandler handler="hotel.tools.HotelTypeHandler"            javaType="hotel.Enum.HotelTypeEnum" jdbcType="VARCHAR" />    </typeHandlers>

测试了一下,可以正确的转化,还有一种配置的方法就是在SqlMapper.xml文件中ResultMap标签下的result标签可以添加TypeHandler属性,只转化这一个查询ResultMap里的值。上一种方式则是全局的转化。

代码举例:

<resultMap type="hotelVO" id="hotelVOResult"><result column="id" property="h_id"/><result column="h_name" property="hname"/><result column="h_type" property="htype" typeHandler="hotel.tools.HotelTypeHandler"/><!-- 其他的很多名字都是和数据库中的名字是一致的,可以直接映射,不需要配 --></resultMap>
测试这两种方式都是可行的。



有什么不足的地方请多指教。



0 0