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

本文介绍了MyBatis中的TypeHandler接口,详细解释了其实现原理及如何自定义TypeHandler来处理特定的数据类型转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     在最近的学习中遇到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.java
public 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>{

	@Override
	public HotelTypeEnum getResult(ResultSet arg0, String arg1)
			throws SQLException {
		return HotelTypeEnum.valueOf(arg0.getString(arg1));
	}

	@Override
	public HotelTypeEnum getResult(ResultSet arg0, int arg1) throws SQLException {
		return HotelTypeEnum.valueOf(arg0.getString(arg1));
	}

	@Override
	public HotelTypeEnum getResult(CallableStatement arg0, int arg1)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public 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>
	
测试这两种方式都是可行的。



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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值