springboot

自定义枚举 --- MyBatis字段映射

2018-09-24  本文已影响177人  十毛tenmao

MyBatis自带的EnumTypeHandler转换为文字保存在数据库,EnumOrdinalTypeHandler使用的是序号,它们的一致性都可能被轻易地破坏,所以最好的办法是自定义一个int类型

自定义公共父接口

package com.tenmao.utils.mybatis;

import java.util.Arrays;
import java.util.Optional;

public interface CodedEnum {
    int getCode();

    static <E extends Enum<?> & CodedEnum> Optional<E> codeOf(Class<E> enumClass, int code) {
        return Arrays.stream(enumClass.getEnumConstants()).filter(e -> e.getCode() == code).findAny();
    }
}

Enum的转换工具类

package com.tenmao.utils.mybatis.handler;

import com.tenmao.utils.mybatis.CodedEnum;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.sql.*;
import java.util.Optional;

@MappedTypes({CodedEnum.class})
public class CodedEnumTypeHandler<E extends Enum<?> & CodedEnum> implements TypeHandler<E> {
    private Class<E> type;

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

    @Override
    public void setParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            ps.setNull(i, Types.TINYINT);
        } else {
            ps.setInt(i, parameter.getCode());
        }
    }

    @Override
    public E getResult(ResultSet rs, String columnName) throws SQLException {
        int columnValue = rs.getInt(columnName);
        return rs.wasNull() ? null : enumOf(columnValue);
    }

    @Override
    public E getResult(ResultSet rs, int columnIndex) throws SQLException {
        int columnValue = rs.getInt(columnIndex);
        return rs.wasNull() ? null : enumOf(columnValue);
    }

    @Override
    public E getResult(CallableStatement cs, int columnIndex) throws SQLException {
        int columnValue = cs.getInt(columnIndex);
        return cs.wasNull() ? null : enumOf(columnValue);
    }

    private E enumOf(int code) {
        final Optional<E> codedEnumOpt = CodedEnum.codeOf(type, code);
        if (codedEnumOpt.isPresent()) {
            return codedEnumOpt.get();
        } else {
            throw new IllegalArgumentException("Cannot convert " + code + " to " + type.getSimpleName() + " by code value.");
        }
    }
}

配置使用转换工具类

data-applicationContext.xml

    <bean id="data-sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="mapperLocations">
            <list>
                <value>classpath*:mapper/*Mapper.xml</value>
            </list>
        </property>
        <property name="dataSource" ref="data-datasource" />
        <property name="configuration" ref="mybatisConfig" />
        <property name="typeHandlersPackage" value="com.tenmao.utils.mybatis.handler" />
    </bean>

自定义枚举

package com.tenmao.utils.model;

import com.tenmao.utils.mybatis.CodedEnum;

public enum Weekday implements CodedEnum {
    MONDAY(1),
    TUESDAY(2),
    WEDNESDAY(3),
    THURSDAY(4),
    FRIDAY(5),
    SATURDAY(6),
    SUNDAY(7)
    private final int code;

    Weekday (int code) {
        this.code = code;
    }

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

ps: 参考资料写得特别好,我之所以重新写了一下,是资料写得有点啰嗦,比如子类的注册,其实都是自动的,不需要再额外配置

自定义枚举系列

参考

上一篇下一篇

猜你喜欢

热点阅读