16、通用枚举类型处理(一)

问题

如果一个项目中,有几十个,几百个,甚至更多的枚举类型怎么办?

如果遇到一个枚举类,写一个TypeHandle,这样的话,枚举类的处理器会剧增。
不仅如此,你会发现,枚举类的处理器几乎大同小异。

解决的思路

定义一个万能的枚举转换处理器,使用泛型实现

定义枚举接口

package com.lf;

/**
 * Created by LF on 2017/6/12.
 */
public interface BaseEnum<E extends Enum<?>, T> {

    T getCode();

    String getName();

    E of(String code);
}

实现枚举接口,定义枚举

package com.lf.dict;

import com.lf.BaseEnum;
import lombok.ToString;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by LF on 2017/6/12.
 */
@ToString
public enum Gender implements BaseEnum<Gender, Integer> {
    MAN(1, "男"),
    WOMAN(2, "女");

    static Map<Integer, Gender> enumMap = new HashMap<>();

    static {
        Gender[] values = Gender.values();
        for (Gender value : values) {
            enumMap.put(value.getCode(), value);
        }
    }

    private Integer code;
    private String name;

    Gender(Integer code, String name) {
        this.code = code;
        this.name = name;
    }

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

    public void setCode(Integer code) {
        this.code = code;
    }

    @Override
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public Gender of(String code) {
        return enumMap.get(code);
    }
}

定义万能枚举转换处理器

package com.lf.typehandle;

import com.lf.BaseEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

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

/**
 * Created by LF on 2017/6/12.
 */
@MappedTypes(basePackage = {"com.lf.dict"})
@MappedJdbcTypes(value = JdbcType.INTEGER, includeNullJdbcType = true)
public class BaseEnumTypeHandle<E extends BaseEnum> extends BaseTypeHandler<E> {

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

    /**
     * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现
     *
     * @param type 配置文件中设置的转换类
     */
    public BaseEnumTypeHandle(Class<E> type) {
        if (type == null)
            throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;

        this.enums = type.getEnumConstants();
        Class<?>[] interfaces = type.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            Object[] enumConstants = anInterface.getEnumConstants();

        }
//        this.enums =  type.getGenericInterfaces();
        if (this.enums == null)
            throw new IllegalArgumentException(type.getSimpleName()
                    + " does not represent an enum type.");
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
                                    JdbcType jdbcType) throws SQLException {
        //BaseTypeHandler已经帮我们做了parameter的null判断
        ps.setObject(i, (String) parameter.getCode(), jdbcType.TYPE_CODE);
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
        String i = rs.getString(columnName);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的value值,定位PersonType子类
            return locateEnumStatus(i);
        }
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
        String i = rs.getString(columnIndex);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的value值,定位PersonType子类
            return locateEnumStatus(i);
        }
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        // 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
        String i = cs.getString(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的value值,定位PersonType子类
            return locateEnumStatus(i);
        }
    }

    /**
     * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷
     *
     * @param value 数据库中存储的自定义value属性
     * @return value对应的枚举类
     */
    private E locateEnumStatus(String value) {
        for (E e : enums) {
            if (e.getCode().equals(value)) {
                return e;
            }
        }
        throw new IllegalArgumentException("未知的枚举类型:" + value + ",请核对" + type.getSimpleName());
    }
}

配置

 <typeHandlers>
        <typeHandler  handler="com.lf.typehandle.BaseEnumTypeHandle" javaType="com.lf.dict.Gender"/>
    </typeHandlers>

配置需要转换的字段

  <resultMap id="BaseResultMap" type="com.lf.entity.Blog">
    <id column="id" jdbcType="VARCHAR" property="id" />
    <result column="title" jdbcType="VARCHAR" property="title" />
    <result column="url" jdbcType="VARCHAR" property="url" typeHandler="com.lf.typehandle.BaseEnumTypeHandle"/>
    <result column="userid" jdbcType="VARCHAR" property="userid"  />
  </resultMap>

这样,我们就不需要为每一个枚举创建一个Handler去自动转换数据库中的枚举了。
仅是这样的话和org.apache.ibatis.type.EnumOrdinalTypeHandler就没有什么区别了,我们写这个类就完全没有必要了

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值