mybatis 枚举自动转换

基于springboot 整合mybatis  tk.mybatis   修改配置没有生效,只好重写 EnumTypeHandler 类

springboot 中 mybatis configuration 配置失效问题:https://blog.csdn.net/Keith003/article/details/84289638

结构如下

1、创建 BaseEnums 枚举公用接口

import java.io.Serializable;


public interface BaseEnums<E extends Enum<?>,T> extends Serializable {
    public String getLabel();
    public T getValue();

}

2、重写 EnumTypeHandler 类

package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class EnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
    private BaseTypeHandler typeHandler = null;

    public EnumTypeHandler(Class<E> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        if(isInterface(type, "BaseEnums接口得全路径")){
            // 如果实现了 BaseEnums 则使用我们自定义的转换器
            typeHandler = new CurrencyEnumHandler(type);
        }else {
            // 默认转换器 也可换成 EnumOrdinalTypeHandler
            typeHandler = new DefaultEnumTypeHandler<>(type);
        }
    }

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

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return (E) typeHandler.getNullableResult(rs,columnName);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return (E) typeHandler.getNullableResult(rs,columnIndex);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return (E) typeHandler.getNullableResult(cs,columnIndex);
    }

    /***************************************************************************
     * 判断对象o实现的所有接口中是否有szInterface
     * 2008-08-07修正多继承中判断接口的功能,
     * 以及修正接口继承后的判断功能
     * package test;
     *
     * public interfaceITest extends Serializable
     * public classTest1 implements ITest
     * public classTest2 extends Test1
     * public classTest3 extends Test2
     *
     * isInterface(Test3.class,"java.io.Serializable")=true
     * isInterface(Test3.class,"test.ITest")=true
     * @paramc
     * @paramsz Interface
     * @return
     */
    public boolean isInterface(Class c, String szInterface) {
        Class[] face = c.getInterfaces();
        for(int i=0,j = face.length; i<j; i++)
        {
            if(face[i].getName().equals(szInterface)) {
                return true;
            }else {
                Class[]face1 = face[i].getInterfaces();
                for(int x=0; x < face1.length; x++)
                {
                    if(face1[x].getName().equals(szInterface)) {
                        return true;
                    } else if(isInterface(face1[x],szInterface)) {
                        return true;
                    }
                }
            }
        }
        if(null!=c.getSuperclass()) {
            return isInterface(c.getSuperclass(),szInterface);
        }
        return false;
    }
}

3、创建 DefaultEnumTypeHandler类 内容为mybatis 中 EnumTypeHandler 类内容  为了不影响除枚举外得转换

package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DefaultEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E>  {
    private final Class<E> type;

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

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            ps.setString(i, parameter.name());
        } else {
            ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589
        }
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String s = rs.getString(columnName);
        return s == null ? null : Enum.valueOf(type, s);
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String s = rs.getString(columnIndex);
        return s == null ? null : Enum.valueOf(type, s);
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String s = cs.getString(columnIndex);
        return s == null ? null : Enum.valueOf(type, s);
    }
}

4、创建  CurrencyEnumHandler类  自定义枚举转换类

package org.apache.ibatis.type;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * class_name: CurrencyEnumHandler
 * package: org.apache.ibatis.type
 * describe: 枚举转换类
 * creat_date: 2018/11/19
 * creat_time: 10:43
 **/
public class CurrencyEnumHandler<E extends Enum<E> & BaseEnums> extends BaseTypeHandler<E>{

    private Class<E> type;

    /**
     * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现
     * @param type 配置文件中设置的转换类
     */
    public CurrencyEnumHandler(Class<E> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
    }
    /**
     * class_name:
     * param: 
     * describe: 用于定义设置参数时,该如何把 Java 类型的参数转换为对应的数据库类型
     * creat_date: 2018/11/19
     * creat_time: 11:34
     **/
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
                                    JdbcType jdbcType) throws SQLException {
        //BaseTypeHandler已经帮我们做了parameter的null判断
        if (jdbcType == null) {
            ps.setObject(i, getFieldValueByFieldName("value",parameter));
        } else {
            ps.setObject(i, getFieldValueByFieldName("value",parameter), jdbcType.TYPE_CODE);
        }
    }
    /**
     * class_name:
     * param: 
     * describe: 用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的 Java 类型
     * creat_date: 2018/11/19
     * creat_time: 11:39
     **/
    @Override
    public E getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        // 根据数据库存储类型决定获取类型
        Object code = rs.getObject(columnName);
        return rs.wasNull() ? null :  codeOf(code);
    }
    /**
     * class_name:
     * param: 
     * describe: 用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的 Java 类型
     * creat_date: 2018/11/19
     * creat_time: 11:41
     **/
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        Object code = rs.getObject(columnIndex);
        return rs.wasNull() ? null :  codeOf(code);
    }
    /**
     * class_name: 
     * param: 
     * describe: 用定义调用存储过程后,如何把数据库类型转换为对应的 Java 类型
     * creat_date: 2018/11/19
     * creat_time: 11:42
     **/
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        Object code = cs.getObject(columnIndex);
        return cs.wasNull() ? null : codeOf(code);
    }
    /**
     * class_name: 
     * param:
     * describe: 获取枚举
     * creat_date: 2018/11/19
     * creat_time: 19:54
     **/
    private E codeOf(Object code){
        try {
            Method codeOf = type.getMethod("codeOf", Object.class);
            Object invoke = codeOf.invoke(codeOf, code);
            return (E)invoke;
        } catch (Exception ex) {
            throw new IllegalArgumentException("Cannot convert " + code + " to " + type.getSimpleName() + " by code value.", ex);
        }
    }

    /**
     * 根据属性名获取属性值
     *
     * @param fieldName
     * @param object
     * @return
     */
    private Object getFieldValueByFieldName(String fieldName, Object object) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            //设置对象的访问权限,保证对private的属性的访问
            field.setAccessible(true);
            return  field.get(object);
        } catch (Exception e) {
            return null;
        }
    }


}

5、创建自己得枚举 实现BaseEnums 接口

package mmall.enums;

import com.fasterxml.jackson.annotation.JsonValue;

/**
 * class_name: UpperLowerShelfStateEnum
 * package: mmall.enums
 * describe: 活动上下架枚举状态
 *              0:待上架   1:上架    2:下架
 * creat_date: 2018/11/19
 * creat_time: 10:38
 **/
public enum UpperLowerShelfStateEnum implements BaseEnums<UpperLowerShelfStateEnum, String> {

    To_be_on_the_shelfteacher("待上架","0"),
    On_the_shelf("上架","1"),
    Lower_frame("下架","2");

    private String value;
    private String lable;

    private UpperLowerShelfStateEnum(String lable, String value) {
        this.value = value;
        this.lable = lable;
    }
    @JsonValue
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }

    public String getLabel() {
        return lable;
    }
    public void getLabel(String lable) {
        this.lable = lable;
    }
    /**
    * 通过value 值进行查找对应枚举
    */
    public static UpperLowerShelfStateEnum codeOf(Object code){
        UpperLowerShelfStateEnum[] values = UpperLowerShelfStateEnum.values();
        for (UpperLowerShelfStateEnum e : values) {
            if (e.getValue().equals(code)) {
                return e;
            }
        }
        return null;
    }
}

注:本文中向数据库中保存得是枚举中value 值 如果需要 可自行修改

猜你喜欢

转载自blog.csdn.net/Keith003/article/details/84290430
今日推荐