Mybatis中自定义TypeHandler处理枚举详解
在Mybatis中,处理枚举类的TypeHandler有两个:
- EnumTypeHandler:用于保存枚举名
- EnumOrdinalTypeHandler:用于保存枚举的序号。
在实际项目中,以上往往不能满足我们的需求。
需求分析
枚举需要包含两个属性,label(用于显示),value(实际的枚举值)。数据库保存枚举值(value)。
这很明显Mybatis提供的两个枚举TypeHandler不能满足我们的需求。此时,我们可以自定义一个通用的枚举TypeHandler来满足我们的需求。
自定义枚举TypeHandler
通用枚举DisplayedEnum
publicinterfaceDisplayedEnum{
StringDEFAULT_VALUE_NAME="value";
StringDEFAULT_LABEL_NAME="label";
defaultIntegergetValue(){
Fieldfield=ReflectionUtils.findField(this.getClass(),DEFAULT_VALUE_NAME);
if(field==null)
returnnull;
try{
field.setAccessible(true);
returnInteger.parseInt(field.get(this).toString());
}catch(IllegalAccessExceptione){
thrownewRuntimeException(e);
}
}
@JsonValue
defaultStringgetLabel(){
Fieldfield=ReflectionUtils.findField(this.getClass(),DEFAULT_LABEL_NAME);
if(field==null)
returnnull;
try{
field.setAccessible(true);
returnfield.get(this).toString();
}catch(IllegalAccessExceptione){
thrownewRuntimeException(e);
}
}
static<TextendsEnum<T>>TvalueOfEnum(Class<T>enumClass,Integervalue){
if(value==null)
thrownewIllegalArgumentException("DisplayedEnumvalueshouldnotbenull");
if(enumClass.isAssignableFrom(DisplayedEnum.class))
thrownewIllegalArgumentException("illegalDisplayedEnumtype");
T[]enums=enumClass.getEnumConstants();
for(Tt:enums){
DisplayedEnumdisplayedEnum=(DisplayedEnum)t;
if(displayedEnum.getValue().equals(value))
return(T)displayedEnum;
}
thrownewIllegalArgumentException("cannotparseinteger:"+value+"to"+enumClass.getName());
}
}
说明:
普通枚举类通过实现DisplayedEnum接口,就可以:
- 通过getValue()获取枚举值。
- 通过getLabel()获取枚举的label属性。
- 通过valueOfEnum()将Integer值转换为指定的枚举类型。
普通枚举类
publicenumCommonsTypeimplementsDisplayedEnum{
NORMAL("正常",0),INVALID("无效",1);
Stringlabel;
Integervalue;
privateCommonsType(Stringlabel,Integervalue){
this.label=label;
this.value=value;
}
}
以上就是一个普通枚举类的示例。
自定义枚举TypeHandler
@MappedJdbcTypes(value=JdbcType.TINYINT,includeNullJdbcType=true)
publicclassDefaultEnumTypeHandlerextendsBaseTypeHandler<DisplayedEnum>{
privateClass<DisplayedEnum>type;
publicEnumTypeHandler(){};
publicEnumTypeHandler(Class<DisplayedEnum>type){
if(type==null)thrownewIllegalArgumentException("Typeargumentcannotbenull");
this.type=type;
}
@Override
publicvoidsetNonNullParameter(PreparedStatementps,inti,DisplayedEnumparameter,JdbcTypejdbcType)
throwsSQLException{
ps.setInt(i,parameter.getValue());
}
@Override
publicDisplayedEnumgetNullableResult(ResultSetrs,StringcolumnName)throwsSQLException{
returnconvert(rs.getInt(columnName));
}
@Override
publicDisplayedEnumgetNullableResult(ResultSetrs,intcolumnIndex)throwsSQLException{
returnconvert(rs.getInt(columnIndex));
}
@Override
publicDisplayedEnumgetNullableResult(CallableStatementcs,intcolumnIndex)throwsSQLException{
returnconvert(cs.getInt(columnIndex));
}
privateDisplayedEnumconvert(intstatus){
DisplayedEnum[]objs=type.getEnumConstants();
for(DisplayedEnumem:objs){
if(em.getValue()==status){
returnem;
}
}
returnnull;
}
}
使用我们自定义的DefaultEnumTypeHandler
由于Mybatis默认在处理枚举类型的时候会使用EnumTypeHandler(只保存及转换枚举类型的名字),因此,我们需要手动指定使用DefaultEnumTypeHandler。示例如下:
<resultMapid="xxx"type="xxx"> ... <resultcolumn="type"jdbcType="TINYINT"property="type"typeHandler="xxx.xxx.xxx.DefaultEnumTypeHandler"/> ... </resultMap>
即我们需要通过使用typeHandler来指定。
小结
以上是我们应用在实际项目中的一个对于Mybatis处理枚举类的方案。我看大多数人也都是这样在用。然而,在实际项目中,我们会发现随着枚举类的增多,这样写起来会很繁琐。我看了一下网络上似乎也没人处理这种情况。那么,下一篇文章将针对这种情况进行处理。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!