在Mybatis中,处理枚举类的TypeHandler有两个:
- EnumTypeHandler: 用于保存枚举名
- EnumOrdinalTypeHandler: 用于保存枚举的序号。
在实际项目中,以上往往不能满足我们的需求。
需求分析
枚举需要包含两个属性,label(用于显示), value(实际的枚举值)。数据库保存枚举值(value)。
这很明显Mybatis提供的两个枚举TypeHandler不能满足我们的需求。此时,我们可以自定义一个通用的枚举TypeHandler来满足我们的需求。
自定义枚举TypeHandler
通用枚举DisplayedEnum
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
public interface DisplayedEnum {
String DEFAULT_VALUE_NAME = "value" ;
String DEFAULT_LABEL_NAME = "label" ;
default Integer getValue() {
Field field = ReflectionUtils.findField( this .getClass(), DEFAULT_VALUE_NAME);
if (field == null )
return null ;
try {
field.setAccessible( true );
return Integer.parseInt(field.get( this ).toString());
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@JsonValue
default String getLabel() {
Field field = ReflectionUtils.findField( this .getClass(), DEFAULT_LABEL_NAME);
if (field == null )
return null ;
try {
field.setAccessible( true );
return field.get( this ).toString();
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
static <T extends Enum<T>> T valueOfEnum(Class<T> enumClass, Integer value) {
if (value == null )
throw new IllegalArgumentException( "DisplayedEnum value should not be null" );
if (enumClass.isAssignableFrom(DisplayedEnum. class ))
throw new IllegalArgumentException( "illegal DisplayedEnum type" );
T[] enums = enumClass.getEnumConstants();
for (T t: enums) {
DisplayedEnum displayedEnum = (DisplayedEnum)t;
if (displayedEnum.getValue().equals(value))
return (T) displayedEnum;
}
throw new IllegalArgumentException( "cannot parse integer: " + value + " to " + enumClass.getName());
}
}
|
说明:
普通枚举类通过实现DisplayedEnum接口,就可以:
- 通过getValue()获取枚举值。
- 通过getLabel()获取枚举的label属性。
- 通过valueOfEnum()将Integer值转换为指定的枚举类型。
普通枚举类
1
2
3
4
5
6
7
8
9
|
public enum CommonsType implements DisplayedEnum {
NORMAL( "正常" , 0 ), INVALID( "无效" , 1 );
String label;
Integer value;
private CommonsType(String label, Integer value) {
this .label = label;
this .value = value;
}
}
|
以上就是一个普通枚举类的示例。
自定义枚举TypeHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
@MappedJdbcTypes (value = JdbcType.TINYINT, includeNullJdbcType = true )
public class DefaultEnumTypeHandler extends BaseTypeHandler<DisplayedEnum> {
private Class<DisplayedEnum> type;
public EnumTypeHandler(){};
public EnumTypeHandler(Class<DisplayedEnum> type) {
if (type == null ) throw new IllegalArgumentException( "Type argument cannot be null" );
this .type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, DisplayedEnum parameter, JdbcType jdbcType)
throws SQLException {
ps.setInt(i, parameter.getValue());
}
@Override
public DisplayedEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
return convert(rs.getInt(columnName));
}
@Override
public DisplayedEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return convert(rs.getInt(columnIndex));
}
@Override
public DisplayedEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return convert(cs.getInt(columnIndex));
}
private DisplayedEnum convert( int status){
DisplayedEnum[] objs = type.getEnumConstants();
for (DisplayedEnum em: objs){
if (em.getValue() == status){
return em;
}
}
return null ;
}
}
|
使用我们自定义的DefaultEnumTypeHandler
由于Mybatis默认在处理枚举类型的时候会使用EnumTypeHandler(只保存及转换枚举类型的名字), 因此,我们需要手动指定使用DefaultEnumTypeHandler。示例如下:
1
2
3
4
5
|
<resultMap id= "xxx" type= "xxx" >
...
<result column= "type" jdbcType= "TINYINT" property= "type" typeHandler= "xxx.xxx.xxx.DefaultEnumTypeHandler" />
...
</resultMap>
|
即我们需要通过使用typeHandler来指定。
小结
以上是我们应用在实际项目中的一个对于Mybatis处理枚举类的方案。我看大多数人也都是这样在用。然而,在实际项目中,我们会发现随着枚举类的增多,这样写起来会很繁琐。我看了一下网络上似乎也没人处理这种情况。那么,下一篇文章将针对这种情况进行处理。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持服务器之家!
原文链接:http://www.cnblogs.com/dongying/p/6410889.html