zoukankan      html  css  js  c++  java
  • mybatis类型转换器

    在数据模型、接口参数等场景部分属性参数为一些常量值,比如性别:男、女。若是定义成int或String类型,于是类型本身的范围太宽,要求使用者需要了解底层的业务方可知如何传值,那整体来看增加沟通成本,对接效率也低。面对此等业务,使用枚举简便许多。枚举enum像个固定常量类,也像一个数组。

    public enum Sex {
    Male(1,"男"),
    FeMale(2,"女"),
    ;
    private int index;
    private String description;
    Sex(int index, String description){
    this.index = index;
    this.description = description;
    }
    public int getIndex() {
    return index;
    }
    public String getDescription() {
    return description;
    }
    }

    定义枚举,存储到数据库为int。这里就需要使用上mybatis的类型处理器功能。mybatis定义了接口TypeHandler用于数据转换。

    public interface TypeHandler<T> {
    void setParameter(PreparedStatement var1, int var2, T var3, JdbcType var4) throws SQLException;
    T getResult(ResultSet var1, String var2) throws SQLException;
    T getResult(ResultSet var1, int var2) throws SQLException;
    T getResult(CallableStatement var1, int var2) throws SQLException;
    }

    mybatis内置了许多类型处理器:IntegerTypeHandlerBigDecimalTypeHandlerEnumTypeHandlerEnumOrdinalTypeHandler

    EnumTypeHandler 数据库字符串类型,用以存储枚举的名称(Male, FeMale);

    EnumOrdinalTypeHandler 数据库为数值类型,存储枚举的序数值

    从 3.4.5 开始,MyBatis 默认支持 JSR-310(日期和时间 API):LocalDateTypeHandlerLocalDateTimeTypeHandler等。

    你可以重写或自定义实现所需的类型转换器,实现org.apache.ibatis.type.TypeHandler 接口 或者继承一个很便利的类 org.apache.ibatis.type.BaseTypeHandler。

    mybatis默认的枚举实现类,不能把index存入数据库中,因此需自定义实现器。

    在项目定义的枚举不止一个,若是单个枚举转换,代码成本太高,维护扩展也困难。那有没有办法写一个通用的转换器呢?

    可以的。

    一、为了区分那些需要转换的枚举,提取些共同属性,定义成接口,需转皆实现此接口即可。

    public interface BaseEnum{
    int getIndex();
    String getDescription();
    }
    public enum Sex implements BaseEnum{
    Male(1,"男"),
    FeMale(2,"女"),
    ;
    private int index;
    private String description;
    Sex(int index, String description){
    this.index = index;
    this.description = description;
    }
    public int getIndex() {
    return index;
    }
    public String getDescription() {
    return description;
    }
    }

     二、自定义类型转换器AutoGenericEnumTypeHandler,继承BaseTypeHandler。因为是通用类型,所以使用到java 泛型的参数


    public class AutoGenericEnumTypeHandler<E extends BaseEnum> extends BaseTypeHandler<E> {

    private Class<E> enumType;
    private E[] enums;

    public AutoGenericEnumTypeHandler(){}

    public AutoGenericEnumTypeHandler(Class<E> type){
    if (type == null) {
    throw new IllegalArgumentException("Type argument cannot be null");
    }
    this.enumType = type;
    this.enums = type.getEnumConstants();
    if (this.enums == null) {
    throw new IllegalArgumentException(type.getName() + " does not represent an enum type.");
    }
    }

    private E loadEnum(int index) {
    for (E e : enums) {
    if (e.getIndex() == index) {
    return e;
    }
    }
    throw new IllegalArgumentException(enumType.getName() + " unknown enumerated type index:" + index);
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
    ps.setInt(i, parameter.getIndex());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
    if(rs.getObject(columnName) == null){
    return null;
    }
    int index = rs.getInt(columnName);
    return loadEnum(index);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    if(rs.getObject(columnIndex) == null){
    return null;
    }
    int index = rs.getInt(columnIndex);
    return loadEnum(index);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    if(cs.getObject(columnIndex) == null){
    return null;
    }
    int index = cs.getInt(columnIndex);
    return loadEnum(index);
    }
    }

     三、配置使用。3.4.5版本后提供配置默认枚举转换器即,不用侵入写代码(侵入写法源代码下载路径:https://gitee.com/zss_376987715/mybatis-dao)

    spring boot的配置:mybatis.configuration.default-enum-type-handler=com.XXX.typehandler.AutoGenericEnumTypeHandler

    spring项目通过mybatis-config.xml配置文件:

    <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    <settings>
    <setting name="defaultEnumTypeHandler" value="com.XXX.typehandler.AutoGenericEnumTypeHandler"/>
    </settings>
    </configuration>

    到此已经实现转换。

    如果正在参照(https://www.cnblogs.com/song27/p/10977241.html)学习多数据源。需要对代码有点改动。

    在创建SqlSessionFactory 时,添加MybatisProperties mybatisProperties参数,重新加载configuration。不然spring boot的application.properties配置不会生效。因为未加载进去。


    @Bean
    public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource, MybatisProperties mybatisProperties) throws Exception {
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(dataSource);
    sessionFactory.setConfiguration(mybatisProperties.getConfiguration());
    return sessionFactory.getObject();
    }
  • 相关阅读:
    VS调试问题整理 :无法在Web服务器上启动调试。您不具备调试此应用程序的权限...
    WebService参考 :什么是Web Services?(AMT研究院 袁磊)
    .NET和J2EE该相互学习什么?(转)
    使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码 (实例)
    C#参考 :ReferenceEquals, == , Equals
    使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码(详解)
    HTML参考 :TBODY元素 详解
    Indigo参考 (2) DataContract 使用 详解(转)
    Indigo参考 (1) :第一个Indigo Service (转)
    控件用法参考:DataList和Repeater控件的分页显示功能
  • 原文地址:https://www.cnblogs.com/song27/p/10999837.html
Copyright © 2011-2022 走看看