欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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解读

希望能帮到大家理解。如果有什么问题可以及时沟通。至于使用在网上很多。只是解释一下mybatis的handler的疑问。有什么好的想法可以留言共同探讨一下。

相关标签: mybatis enum