当前使用版本(必填,否则不予处理)
<mybatis-plus.version>3.3.2</mybatis-plus.version>
在最新的3.4.2版本也测试过了,问题一致
该问题是如何引起的?(确定最新版也有问题再提!!!)
片段一-没问题的版本:
@AllArgsConstructor
@Getter
public enum Level {
ROOT("根目录", "0", 0),
FIRST("一级", "1", 1),
SECOND("二级", "2", 2),
THIRD("三级", "3", 3);
private String name;
private String codeStr;
@EnumValue
private Integer code;
}
片段二-添加抽象方法,@EnumValue不生效
@AllArgsConstructor
@Getter
public enum Level {
ROOT("根目录", "0", 0){
@Override
public Level child() {
return FIRST;
}
},
FIRST("一级", "1", 1){
@Override
public Level child() {
return SECOND;
}
},
SECOND("二级", "2", 2){
@Override
public Level child() {
return THIRD;
}
},
THIRD("三级", "3", 3) {
@Override
public Level child() {
return null;
}
};
private String name;
private String codeStr;
public abstract Level child();
@EnumValue
private Integer code;
}
重现步骤(如果有就写完整)
1.片段一未添加过抽象方法的实现,使用情况正常 2.片段二为每个枚举类添加抽象方法实现,发现注解@EnumValue不生效
报错信息
sql查询类型错误,没有走code这个Integer值
Comment From: plusmancn
@yoko-murasame 代码片段建议使用 markdown code block 描述,这会让问题表述更加整洁清晰
Comment From: plusmancn
@yoko-murasame 3.4.2 下无法复现你的问题
Comment From: yoko-murasame
@yoko-murasame 3.4.2 下无法复现你的问题
感谢帮助,我用的数据库是pgsql13,这个也许是数据库问题?
Comment From: plusmancn
可以断点调试下 com/baomidou/mybatisplus/core/handlers/MybatisEnumTypeHandler.java#getNullableResult 方法看下,光看 valueOf 方法,和数据库关系不大。
Comment From: yoko-murasame
可以断点调试下
com/baomidou/mybatisplus/core/handlers/MybatisEnumTypeHandler.java#getNullableResult方法看下,光看valueOf方法,和数据库关系不大。
我今天新建了个demo,测试了下3.4.2版本,数据库pgsql13,也没发现问题,目前来看是原先项目中其他框架引起的(推测是druid 1.1.21 的影响),最后非常感谢您的帮助!
Comment From: octyu
同遇到了这个问题,在枚举类的抽象方法中去进行数据库操作 @EnumValue 就会失效,否则是正常的。
Comment From: ya0yy
不是抽象方法导致的,是枚举的实现体导致的。
@Getter
@RequiredArgsConstructor
enum PayMethodEnum {
ALIPAY(1), WECHAT_PAY(2), OTHER(3);
@EnumValue
private final int code;
}
以上例子中,枚举成员ALIPAY、WECHAT_PAY、OTHER都属于PayMethodEnum类型,即这三者getClass()的结果都是PayMethodEnum.class
@Getter
@RequiredArgsConstructor
enum PayMethodEnum {
ALIPAY(1) {
@Override
public String toString() {
return getCode() + "";
}
},
WECHAT_PAY(2) {
},
OTHER(3);
@EnumValue
private final int code;
}
上面这个版本中成员ALIPAY重写了toString方法,而WECHAT_PAY只有一对大括号什么方法都没有实现,此时ALIPAY、WECHAT_PAY虽然也都属于PayMethodEnum类型,但实际上getClass()的结果是PayMethodEnum$序号,这里的'序号'是个变量,根据java编译匿名内部类的规则,会依次在当前类名的名字后面拼接'序号'来当作匿名内部类的类名。所以ALIPAY调用getClass()的结果是PayMethodEnum$1.class,WECHAT_PAY是PayMethodEnum$2.class。而mybatis底层的机制是调用传入的参数对象的getClass根据该对象的所属class去获取handlerType,而mybatis-plus帮我们注册的处理枚举类型的handlerType(类型是MybatisHandlerType)映射的是PayMethodEnum.class,所以此时通过PayMethodEnum$1.class去获取handlerType是拿不到的,最终会走到mybatis自带的默认的枚举类型处理器(EnumTypeHandler)。
解决方案
我将mybatis的默认设置为mybatis-plus提供的枚举类型处理器解决了该问题
# application.yml配置文件
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
以上均为鄙人拙见,如有纰漏还请指正