问题
如果一个项目中,有几十个,几百个,甚至更多的枚举类型怎么办?
如果遇到一个枚举类,写一个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
就没有什么区别了,我们写这个类就完全没有必要了