1. 程式人生 > >mybatis入庫的Handler解讀

mybatis入庫的Handler解讀

需要將前臺傳遞過來的列舉類處理為列舉的值。所以抄著網路一段處理列舉的程式碼。

解讀過程

定義列舉類時候需要實現一個數字裝換介面。具體程式碼如下:

@EnumTags(alias = "orderStatusEnum")
public enum OrderStatusEnum implements IntEnum<OrderStatusEnum> {
    NEW(1),
    UnPay(2),
    UnConfirm(3),
    Confirm(4),
    ConfirmFailed(5),
    UserCancel(6),
    TimeoutCancel(7
), MerchantCancel(8), MerchantRefusedCancel(9), ErpOrderFail(10); private int value; OrderStatusEnum(int value) { this.value = value; } @Override public int getIntValue() { return value; } @Override public String toString() { return
String.valueOf(value); } }

定義和資料庫請求的handler。複製網路如下

/**
 * 處理使用mybatis時候不能查出enmu類和插入時候不能插入titint
 * Created by lijianzhen1 on 2017/3/16.
 */
public class EnumTypeHandler<E extends Enum<E> & IntEnum<E>> extends BaseTypeHandler<IntEnum> {
    private Class<IntEnum> clazz;

    public EnumTypeHandler(Class<IntEnum> enumType) {
        if
(enumType == null) throw new IllegalArgumentException("enumType argument cannot be null"); this.clazz = enumType; } /** * 將資料庫對映的值轉化為對應的列舉值 * * @param code * @return */ private IntEnum convert(int code) { IntEnum[] enumConstants = clazz.getEnumConstants(); for (IntEnum im : enumConstants) { if (im.getIntValue() == code) return im; } return null; } @Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, IntEnum intEnum, JdbcType jdbcType) throws SQLException { preparedStatement.setInt(i, intEnum.getIntValue()); } @Override public IntEnum getNullableResult(ResultSet resultSet, String columnName) throws SQLException { return convert(resultSet.getInt(columnName)); } @Override public IntEnum getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException { return convert(resultSet.getInt(columnIndex)); } @Override public IntEnum getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException { return convert(callableStatement.getInt(columnIndex)); } }

別的handler處理都沒有建構函式去構造,但是上邊的為什麼會有一個構造引數。這個是怎麼實現的。
先找到對應的xml解析registry類XMLMapperBuilder。

//解析xsd註冊得xml部分
ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
//獲得需要持久化解析的引數物件 
Class parameterType = parameterMapBuilder.type();
Class<?> javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType);
//具體的列舉實體型別javaTypeClass
TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
//這裡就將要建立型別的handler
protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType) {
    if (typeHandlerType == null) {
      return null;
    }
    // javaType ignored for injected handlers see issue #746 for full detail
    TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);
    if (handler == null) {
      // not in registry, create a new one
      handler = typeHandlerRegistry.getInstance(javaType, typeHandlerType);
    }
    return handler;
  }
//獲得對應的列舉的handler
public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
    if (javaTypeClass != null) {
      try {
       //主要是這裡。我們獲得handler的構造器,構造器傳遞列舉型別的引數
        Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
        return (TypeHandler<T>) c.newInstance(javaTypeClass);
      } catch (NoSuchMethodException ignored) {
        // ignored
      } catch (Exception e) {
        throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
      }
    }
    try {
     //如果是空的構造器就直接返回預設的構造器。
      Constructor<?> c = typeHandlerClass.getConstructor();
      return (TypeHandler<T>) c.newInstance();
    } catch (Exception e) {
      throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
    }
  }
//sql在執行時候的處理類BaseStatementHandler
//建立引數的預設Handler
XMLLanguageDriver.createParameterHandler()
//DefaultParameterHandler TypeHandlerRegistry在獲得預設註冊的handler時候就是基本型別的zhuangh
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();

這裡寫圖片描述

希望能幫到大家理解。如果有什麼問題可以及時溝通。至於使用在網上很多。只是解釋一下mybatis的handler的疑問。有什麼好的想法可以留言共同探討一下。