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

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

程序员文章站 2022-04-23 15:51:08
...

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

自定义枚举系列

参考