欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Mybatis中自定义TypeHandler处理枚举详解

程序员文章站 2024-03-07 12:17:51
在mybatis中,处理枚举类的typehandler有两个: enumtypehandler: 用于保存枚举名 enumordinaltypehandle...

在mybatis中,处理枚举类的typehandler有两个:

  • enumtypehandler: 用于保存枚举名
  • enumordinaltypehandler: 用于保存枚举的序号。

在实际项目中,以上往往不能满足我们的需求。

需求分析

枚举需要包含两个属性,label(用于显示), value(实际的枚举值)。数据库保存枚举值(value)。

这很明显mybatis提供的两个枚举typehandler不能满足我们的需求。此时,我们可以自定义一个通用的枚举typehandler来满足我们的需求。

自定义枚举typehandler

通用枚举displayedenum

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接口,就可以:

  1. 通过getvalue()获取枚举值。
  2. 通过getlabel()获取枚举的label属性。
  3. 通过valueofenum()将integer值转换为指定的枚举类型。

普通枚举类

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

@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。示例如下:

<resultmap id="xxx" type="xxx">
 ...
 <result column="type" jdbctype="tinyint" property="type" typehandler="xxx.xxx.xxx.defaultenumtypehandler" />
 ...
</resultmap> 

即我们需要通过使用typehandler来指定。

小结

以上是我们应用在实际项目中的一个对于mybatis处理枚举类的方案。我看大多数人也都是这样在用。然而,在实际项目中,我们会发现随着枚举类的增多,这样写起来会很繁琐。我看了一下网络上似乎也没人处理这种情况。那么,下一篇文章将针对这种情况进行处理。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!