Skip to content

Registered type handler is not used for anonymous enums #2956

Closed
@xrayw

Description

@xrayw

Example:

@AllArgsConstructor
@Getter
public enum GcType {
    G1(1),
    ZGC(2) {
        @Override
        public String getName() {
            return "zgc";
        }
    },
    ;

    public String getName() {
        return this.name();
    }

    private int value;
}

Create a custom enum TypeHandler without MappedJdbcTypes for enum GcType named CustomEnumTypeHandler.

@MappedTypes(GcType.class)
public class CustomEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {
   // xxx
}

now the typeHandlerRegistry.typeHandlerMap should be {xx, GcType={null=CustomEnumTypeHandler} , xx}

next step:

use GcType.ZGC as the object param to execute db operation.

class Param {
  private GcType gcType;
}

Mapper {
    @Select("select xxx from xxx where xxx=#{param.gcType}")
    xxx selectXXX(Param param);
}

then call it: selectXXX(new Param(GcType.ZGC))

Because the GcType.ZGC's type is GcType$1, not GcType, so the typeHandlerMap can't find the typeHandler for GcType$1,

TypeHandlerRegistry#getJdbcHandlerMap

// when type = GcType$1
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
    if (jdbcHandlerMap != null) {
      return NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap) ? null : jdbcHandlerMap;
    }
    if (type instanceof Class) {
      Class<?> clazz = (Class<?>) type;
      if (Enum.class.isAssignableFrom(clazz)) {
        Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;    // GcType$1.isAnonymousClass() is true, so enumClass=GcType
        jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
        if (jdbcHandlerMap == null) {
          register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));    // here will replace the previous enumClass's[jdbcType=null]  typehandler
          return typeHandlerMap.get(enumClass);
        }
      } else {
        jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
      }
    }
    typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
    return jdbcHandlerMap;
  }

after the getJdbcHandlerMap method, the typeHandlerMap should be {xx, GcType={null=EnumTypeHandler} , xx}, the original {xx, GcType={null=CustomEnumTypeHandler} , xx} was replaced.

I think we' better keep it use the GcType's jdbcType TypeHandler[CustomEnumTypeHandler] if the jdbcType's TypeHandler exists , instead of replace it..

the original pr change about getJdbcHandlerMap anonymous enum #1490

MyBatis version

3.5.3

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions