mybatis入库的Handler解读
程序员文章站
2022-05-12 11:44:32
...
需要将前台传递过来的枚举类处理为枚举的值。所以抄着网络一段处理枚举的代码。
解读过程
定义枚举类时候需要实现一个数字装换接口。具体代码如下:
@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的疑问。有什么好的想法可以留言共同探讨一下。
推荐阅读