在mybatis中使用枚举和boolean,提供代码可读性

问题描述

实体中的属性使用枚举和boolean会增加代码的可读性,但是实体和数据库的映射上不能很自然地支持,这样导致由于数据库的原因使得实体中属性使用基本类型来代替枚举和boolean。

实体中属性实例如下

private Integer status;// 0:草稿,1:合格 2:优秀 3:退回

private Byte open;//0;关闭 1:打开

在页面,java代码,和sql到处使用数字,使得代码可读性极差,代码越多,时间越长越没法维护。

<#if trainGroup.type==1>

<a href="javascript:" class="zi-lv" onclick="createAllGroup()" >教研组</a>

<#else>

<a href="javascript:" class="zi-lv" onclick="createAllCoop()" >协作组</a>

</#if>

param.setStatus(2); //优秀

或者使用常量(不能保证大家都使用常量,直接使用数字也没有错)param.setStatus(CONST.GOOD); //优秀

select ....

from T_DT_TRAIN_GROUP t .....m.STATUS = 2

使用枚举后的代码如下

<#if trainGroup.type=='JIAOYAN'>

<a href="javascript:" class="zi-lv" onclick="createAllGroup()" >教研组</a>

<#else>

<a href="javascript:" class="zi-lv" onclick="createAllCoop()" >协作组</a>

</#if>

param.setStatus(Status.GOOD);//只能使用枚举,否则编译通不过

select ....

from T_DT_TRAIN_GROUP t .....m.STATUS =${@cn.com.Status@GOOD.getValue()}

解决办法

在mybatis中实体属性与表字段之间的映射使用TypeHandler机制,mybatis本身提供了两种枚举类型的转换 EnumTypeHandler和EnumOrdinalTypeHandler。

EnumTypeHandler:将枚举值转化成字符串,字符串取枚举值的名称,使用枚举的.name()方法。EnumTypeHandler已经被内置了,只需要将实体属性改成枚举即可,不需要做任何TypeHandler配置,下面是mybatis获得TypeHandler的源码,如果没有匹配上任何TypeHandler,并且属性是枚举类型就使用EnumTypeHandler。

private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {

Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);

TypeHandler<?> handler = null;

if (jdbcHandlerMap != null) {

handler = jdbcHandlerMap.get(jdbcType);

if (handler == null) {

handler = jdbcHandlerMap.get(null);

}

}

if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) {

handler = new EnumTypeHandler((Class<?>) type);

}

@SuppressWarnings("unchecked")

// type drives generics here

TypeHandler<T> returned = (TypeHandler<T>) handler;

return returned;

}

这种方式最简洁,不需要做任何配置,但是要求表字段中存储的是枚举的名称。

EnumOrdinalTypeHandler:将枚举值转换数字,使用的是枚举的.ordinal()方法。如果要使用这种方式必须给每一个枚举类配置一次EnumOrdinalTypeHandler,如下给两个枚举配置同一个

EnumOrdinalTypeHandler,没有配置的枚举会走默认的EnumTypeHandler。

<typeHandlers>

<!-- <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"

javaType="cn.com.teacher.cistus.dt.entity.TestMenu" /> -->

<typeHandler

handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"

javaType="cn.com.teacher.cistus.dt.enums.EnumTrainGroupType" />

<typeHandler

handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"

javaType="cn.com.teacher.cistus.dt.enums.EnumPortalConfigType" />

</typeHandlers>

sql mapper中如何使用枚举

public class TrainGroup extends AbstractEntity

private EnumTrainGroupType type;//0教研组 1协作组

映射和查询条件中不用任何特殊处理即可使用枚举。

<resultMap id="BaseResultMap" type="cn.com.teacher.cistus.dt.entity.TrainGroup" >

<result column="TYPE" property="type" jdbcType="INTEGER" />

。。。

<if test="type != null" >

TYPE = #{type,jdbcType=INTEGER},

</if>

sql中使用枚举常量

如下示例直接在sql中使用枚举,这样提高了代码的可读性,并且枚举值写错了会报错提示的。type=${@cn.com.teacher.cistus.

dt.enums.EnumTrainGroupType@JIAOYAN.ordinal()}

枚举常量的获取使用了ongl表达式的功能,${@cn.co。。GroupType@JIAOYAN.ordinal()}是原生的ongl执行静态代码的写法。

枚举值按指定值映射

mybatis本身只提供了上面两种枚举映射方式,如果想映射自定义的值,比如

JIAOYAN(10,"教研组"),XIEZUO(20,"协作组");映射成 10 ,20.

public class EnumValueTypeHandler <E extends Enum & IDBEnum> extends BaseTypeHandler<E>{

private Class<E> type;

// private final E[] enums;

public EnumValueTypeHandler(Class<E> type) {

this.type = type;

E[] enums = type.getEnumConstants();

if (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 {

ps.setInt(i, parameter.getValue());

}

@Override

public E getNullableResult(ResultSet rs, String columnName) throws SQLException {

int i = rs.getInt(columnName);

if (rs.wasNull()) {

return null;

} else {

try {

return DBEnumUtils.getEnumInstance(type,i);

} catch (Exception ex) {

throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);

}

}

}

@Override

public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

int i = rs.getInt(columnIndex);

if (rs.wasNull()) {

return null;

} else {

try {

return DBEnumUtils.getEnumInstance(type,i);

} catch (Exception ex) {

throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);

}

}

}

@Override

public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {

int i = cs.getInt(columnIndex);

if (cs.wasNull()) {

return null;

} else {

try {

return DBEnumUtils.getEnumInstance(type,i);

} catch (Exception ex) {

throw new IllegalArgumentException("Cannot convert " + i + " to " + type.getSimpleName() + " by ordinal value.", ex);

}

}

}

}

public enum EnumTrainGroupType implements IDBEnum{

JIAOYAN(10,"教研组"),XIEZUO(20,"协作组");

private int value;

private String name;

EnumTrainGroupType(int value,String name){

this.value=value;

this.name=name;

}

@Override

public int getValue() {

return value;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public void setValue(int value) {

this.value = value;

}

}

在mybatis中使用枚举和boolean,提供代码可读性

相关推荐