springboot + mybatis 自定義枚舉類型轉換


MyBatis內置了兩個枚舉轉換器分別是:org.apache.ibatis.type.EnumTypeHandler和org.apache.ibatis.type.EnumOrdinalTypeHandler。

EnumTypeHandler是默認的枚舉轉換器,該轉換器將枚舉實例轉換為實例名稱的字符串。比如有個枚舉

NO_RECOVERY(10),使用EnumTypeHandler保存在數據庫中的就是“NO_RECOVERY”

EnumOrdinalTypeHandler這個轉換器將枚舉實例的ordinal屬性作為取值(從0依次取值)。還是上面的例子用這種轉換器保存在數據庫中的值就是0。

 

  如果我們想保存枚舉本身所定義的code值呢?這就需要自定義一個類型轉換器,自定義一個int類型保存在數據庫,即insert時枚舉轉換為int型數據保存在數據庫,select時數據庫中的int值轉換成實

體類的枚舉類型。

 

一、自定義公共父接口

public interface BaseCodeEnum {
    int getCode();
}

 

二、改造枚舉, 需要轉換的枚舉類實現BaseCodeEnum接口

public enum RecoverType implements BaseCodeEnum {
    NO_RECOVERY(10),
    RECOVERY(11),
    PROTECT(12);
    int value;
    RecoverType(int value){
        this.value = value;
    }

    @Override
    public int getCode() {
        return value;
    }
}

public enum TunnelType implements BaseCodeEnum {
    TP("TP"),
    TE("TE"),
    RSVP("RSVP");

    private String name;

    TunnelType(String value) {
        this.name = value;
    }

    public String getValue() {
        return name;
    }

    @Override
    public int getCode() {
        switch (name) {
            case "TP":
                return 1;
            case "TE":
                return 2;case "RSVP":
                return 3;
            default:
                break;
        }

        return 255;
    }
}

 


三、 Enum的轉換工具類

public class CodeEnumUtil {

    public static <E extends Enum<?> & BaseCodeEnum> E codeOf(Class<E> enumClass, int code) {
        E[] enumConstants = enumClass.getEnumConstants();
        for (E e : enumConstants) {
            if (e.getCode() == code)
                return e;
        }
        return null;
    }
}

@MappedTypes({BaseCodeEnum.class}) public class CodeEnumTypeHandler<E extends Enum<?> & BaseCodeEnum> extends BaseTypeHandler<BaseCodeEnum> {

    private Class<E> type;

    public CodeEnumTypeHandler(Class<E> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null.");
        }
        this.type = type;
    }

    //用於定義設置參數時,該如何把Java類型的參數轉換為對應的數據庫類型
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, BaseCodeEnum parameter, JdbcType jdbcType)
            throws SQLException {
        ps.setInt(i, parameter.getCode());
    }

    //用於定義通過字段名稱獲取字段數據時,如何把數據庫類型轉換為對應的Java類型
    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int code = rs.getInt(columnName);
        return rs.wasNull() ? null : codeOf(code);
    }

    //用於定義通過字段索引獲取字段數據時,如何把數據庫類型轉換為對應的Java類型
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int code = rs.getInt(columnIndex);
        return rs.wasNull() ? null : codeOf(code);
    }

    //用定義調用存儲過程后,如何把數據庫類型轉換為對應的Java類型
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int code = cs.getInt(columnIndex);
        return cs.wasNull() ? null : codeOf(code);
    }

    private E codeOf(int code){
        try {
            return CodeEnumUtil.codeOf(type, code);
        } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + code + " to " + type.getSimpleName() + " by code value.", ex);
        }
    }
}

 

三、使用,有兩種方法:

第一種:
  a) MyBatis配置文件中定義typeHandler掃描包路徑
    mybatis:
      ...
      type-handlers-package: com.test.enumconvert

  b) 在自定義的轉換類上加上這個注解 @MappedTypes({BaseCodeEnum.class})

第二種:
  首先,第一種的配置都去掉,修改mapper.xml文件


  a) 實體類 -> 數據庫
  insert時,在values中指定typeHandler,比如
  #{recoverType,jdbcType=INTEGER,typeHandler=com.test.enumconvert.CodeEnumTypeHandler}


  b) 數據庫 -> 實體類
  select時,也要指定typeHandler,比如在resultMap中指定
  <arg column="recover_type" jdbcType="INTEGER" javaType="com.test.pojo.RecoverType" typeHandler="com.test.enumconvert.CodeEnumTypeHandler" />

 

參考:https://www.jianshu.com/p/c84549e0ee10
          https://segmentfault.com/a/1190000010755321


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM