mybatis入庫的Handler解讀
阿新 • • 發佈:2019-01-01
需要將前臺傳遞過來的列舉類處理為列舉的值。所以抄著網路一段處理列舉的程式碼。
解讀過程
定義列舉類時候需要實現一個數字裝換介面。具體程式碼如下:
@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();