天天看點

Mybatis 示例之 TypeHandler

關于​

​TypeHandler​

​的基礎内容可以參考官方中文文檔:

​​http://mybatis.github.io/mybatis-3/zh/configuration.html#typeHandlers​​

​TypeHandler​

​寫起來很容易,但是有一個很重要的點需要注意。

你是否遇到過類似下面的錯誤:

Caused by: java.lang.RuntimeException: 調用方法異常:java.lang.IllegalStateException: Type handler was null on parameter mapping for property 'xxx'.  It was either not specified and/or could not be found for      

如果你遇到了這個問題,那麼這篇部落格正好适合你。如果你還沒遇到,也可以避免遇到這個問題。

先說錯誤的原因,MyBatis在查找類型的​

​TypeHandler​

​的時候,調用下面的方法:

private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
  Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
  TypeHandler<?> handler = null;
  if (jdbcHandlerMap != null) {
    handler = jdbcHandlerMap.get(jdbcType);
    if (handler == null) {
      handler = jdbcHandlerMap.get(null);
    }
  }
  if (handler == null && type != null 
                      && type instanceof Class 
                      && Enum.class.isAssignableFrom((Class<?>) type)) {
    handler = new EnumTypeHandler((Class<?>) type);
  }
  // type drives generics here
  return      

一般情況下我們如果在Mapper.xml中使用的resultType,或者使用的resultMap但是resultMap的配置中沒有指定特殊類型字段的jdbcType,就會出現上面的錯誤。

從上面源碼很容易能看出來,當jdbcType是null的時候:

handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
  handler = jdbcHandlerMap.get(null);
}      

​jdbcHandlerMap.get(jdbcType)​

​​和​

​jdbcHandlerMap.get(null)​

​​作用是一樣的,結果都是​

​null​

​,是以就會報出上面提到的錯誤。

這個錯誤如何解決呢?

如果僅從上面錯誤的原因配置一個jdbcType也解決不了使用resultType時的問題。

從源碼​

​handler = jdbcHandlerMap.get(null);​

​這裡可以看到,預設情況下如果有jdbcType,但是​

​handler=null​

​​,也會嘗試取出一個key為​

​null​

​的handler。

也就是說一般情況下,我們自己配置的​

​TypeHandler​

​​都需要有一個​

​key=null​

​的鍵值。

如何設定一個​

​null​

​​的key呢?如果你認為是枚舉類型​

​JdbcType.NULL​

​那就錯了。

​TypeHandler​

​​有兩種設定​

​null​

​的方式:

1. ​

​@MappedJdbcTypes​

​注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MappedJdbcTypes
    public JdbcType[] value();
    boolean includeNullJdbcType() default false;
}      

該注解包含一個屬性​

​includeNullJdbcType​

​​,将該屬性設定為​

​true​

​即可。

2. xml配置

首先重點說明一下:如果使用了上面的注解配置,那麼在xml中的​

​jdbcType​

​配置不會起作用,會完全使用注解中的配置。

xml配置方法很簡單,那就是不要配置​

​jdbcType​

​屬性,例如:

<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>