English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Detailed Explanation of Customizing TypeHandler for Enum in Mybatis

In Mybatis, there are two TypeHandlers for handling enumeration classes:

  • EnumTypeHandler: Used to save the enumeration name
  • EnumOrdinalTypeHandler: Used to save the enumeration ordinal.

In actual projects, the above often cannot meet our needs.

Requirement Analysis

It is obvious that the two enumeration TypeHandlers provided by Mybatis cannot meet our needs. At this point, we can define a custom general enumeration TypeHandler to meet our needs.

General enumeration DisplayedEnum

Custom enum TypeHandler

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);
 return Integer.parseInt(field.get(this).toString());
 try {
  return null;
 field.setAccessible(true);
  return field.get(this).toString();
  @JsonValue
 }
  throw new RuntimeException(e);
 }
 }
 default String getLabel() {
 Field field = ReflectionUtils.findField(this.getClass(), DEFAULT_LABEL_NAME);
 if (field == null)
 try {
  return null;
 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());
 }
}

Note:

A common enum class can do the following by implementing the DisplayedEnum interface:

  1. Get the enum value via getValue().
  2. Get the enum's label attribute via getLabel().
  3. Convert the Integer value to the specified enum type via valueOfEnum().

Common enum class

public enum CommonsType implements DisplayedEnum {
 NORMAL("Normal", 0), INVALID("Invalid", 1);
 String label;
 Integer value;
 private CommonsType(String label, Integer value) {
 this.label = label;
 this.value = value;
 }
}

The above is an example of a common enum class.

Custom enum 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;
 }
}

Using our custom DefaultEnumTypeHandler

Since Mybatis defaults to using EnumTypeHandler (only saving and converting the names of enum types) when handling enum types, we need to manually specify the use of DefaultEnumTypeHandler. The following is an example:

<resultMap id="xxx" type="xxx">
 ...
 <result column="type" jdbcType="TINYINT" property="type" typeHandler="xxx.xxx.xxx.DefaultEnumTypeHandler"> />
 ...
</resultMap> 

That is, we need to specify through the use of typeHandler.

Summary

The following is a solution for handling enum classes in Mybatis that we have applied in actual projects. I see that most people are using it this way. However, in actual projects, we will find that it will be very cumbersome to write as the number of enum classes increases. I looked at the Internet and it seems that no one has dealt with this situation. So, the next article will deal with this situation.

That's all for this article. I hope the content of this article can bring you some help in learning or working, and I also hope to support the呐喊 tutorial more!

Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report violations, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.)

You May Also Like