mybatis-plus3.0.1枚举返回为null解决办法

作者:SakuyaM 时间:2023-11-07 16:59:50 

mybatis-plus 3.0.1 枚举返回为null解决办法

2020-11-02 14:28:48
今天再次回到代码里无意间看到,原来和mybatis-plus没有关系!发生这个问题的根本原因还是要看是否在对应的Mapper.xml里指定了jdbcType。由于我使用了IDEA的代码生成插件,所以没有再进一步去研究为什么返回的数据类型会是以BigDecimal包装的,就此闹了个笑话。。

结论:枚举类用EnumValue注解修饰的数据类型,例如是Integer,那么在Mapper.xml中的jdbcType需要修改为对应类型!

最好的解决办法就是使用新版的mybatis-plus!

3.1.0版本后改变了mybatis原生的默认行为,而3.1.2版本以下的枚举处理类依然是EnumTypeHandler。推测在3.1.2以上的版本应该是不会出现这个问题的。

项目环境:springboot + oracle + mybatis-plus

实体类引用到的枚举类,实现 IEnum 接口:


package com.abc.common.model.enums;

import com.baomidou.mybatisplus.core.enums.IEnum;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

@Getter
public enum FieldType implements IEnum<Integer> {
 NONE(-1, ""),
 NORMAL_INPUT(0, "文本"),
 BIG_INPUT(1, "多文本"),
 DATETIME(2, "日期时间"),
 DATE(3, "日期"),
 TIME(4, "时间"),
 UPLOAD(5, "文件上传"),
 DICT(6, "字典");

private final Integer value;

@JsonValue
 private final String fieldType;

private static final FieldType[] values = values();

FieldType(Integer value, String fieldType) {
   this.value = value;
   this.fieldType = fieldType;
 }

@JsonCreator
 public static FieldType valueOf(Integer value) {
   for (FieldType enu : values) {
     if (enu.getValue().equals(value)) {
       return enu;
     }
   }

return null;
 }
}

mybatis-plus中关于枚举类的配置:


mybatis-plus:
#其它配置...
type-enums-package: com.abc.common.model.enums
#在3.0.1版本下无法设置默认的枚举类型处理
#default-enum-type-handler: com.abc.service.handler.CustomizeEnumTypeHandler
#其它配置...

前面说过了,项目使用的是mybatis-plus 3.0.1,这里配置default-enum-type-handler是没有作用的。至于为什么不更新,项目是多人协同开发的,公司也不允许私自修改依赖包。

调用接口查询时问题出现了:

mybatis-plus3.0.1枚举返回为null解决办法

日志说明这个字段是有一个有效值的,并且查询出来了。(FIELD_TYPE字段是NUMBER(1)类型)

mybatis-plus3.0.1枚举返回为null解决办法

6对应的枚举值应该是DICT,也就是字典类型才对,但是映射到实体类时却变成了NULL。

在我看了一下午的源码以后发现了问题的原因:
EnumTypeHandler.class:


package com.baomidou.mybatisplus.extension.handlers;

import com.baomidou.mybatisplus.core.enums.IEnum;
import com.baomidou.mybatisplus.core.toolkit.EnumUtils;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class EnumTypeHandler<E extends Enum<?> & IEnum> extends BaseTypeHandler<IEnum> {
 private Class<E> type;

public EnumTypeHandler(Class<E> type) {
   if (type == null) {
     throw new IllegalArgumentException("Type argument cannot be null");
   } else {
     this.type = type;
   }
 }

public void setNonNullParameter(PreparedStatement ps, int i, IEnum parameter, JdbcType jdbcType) throws SQLException {
   if (jdbcType == null) {
     ps.setObject(i, parameter.getValue());
   } else {
     ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
   }

}

public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
   return null == rs.getString(columnName) && rs.wasNull() ? null : EnumUtils.valueOf(this.type, rs.getObject(columnName));
 }

public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
   return null == rs.getString(columnIndex) && rs.wasNull() ? null : EnumUtils.valueOf(this.type, rs.getObject(columnIndex));
 }

public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
   return null == cs.getString(columnIndex) && cs.wasNull() ? null : EnumUtils.valueOf(this.type, cs.getObject(columnIndex));
 }
}

这是mybatis-plus用来处理数值和枚举类之间关系的处理类(这里如果枚举类是用@EnumValue来标注数值的话,处理类是相同包结构下的EnumAnnotationTypeHandler.class,原理相同),可以看到在一些列判空后最后使用EnumUtils工具类来决定返回枚举类里的哪个值。
EnumUtils.class


package com.baomidou.mybatisplus.core.toolkit;

import com.baomidou.mybatisplus.core.enums.IEnum;
import java.lang.reflect.Field;
import java.util.Objects;

public class EnumUtils {
 public EnumUtils() {
 }

public static <E extends Enum<?> & IEnum> E valueOf(Class<E> enumClass, Object value) {
   E[] es = (Enum[])enumClass.getEnumConstants();
   Enum[] var3 = es;
   int var4 = es.length;

for(int var5 = 0; var5 < var4; ++var5) {
     E e = var3[var5];
     if (Objects.equals(((IEnum)e).getValue(), value)) {
       return e;
     }
   }

return null;
 }

public static <E extends Enum<?>> E valueOf(Class<E> enumClass, Object value, Field enumField) {
   E[] es = (Enum[])enumClass.getEnumConstants();
   Enum[] var4 = es;
   int var5 = es.length;

for(int var6 = 0; var6 < var5; ++var6) {
     Enum e = var4[var6];

try {
       if (Objects.equals(enumField.get(e), value)) {
         return e;
       }
     } catch (IllegalAccessException var9) {
     }
   }

return null;
 }
}

理解了源码就发现了问题所在了,让这个EnumUtils返回null值的情况,大概是Objects.equals()判断值是否相等时,找不到这个枚举类里面有任何和查询出来的值相同的值。

mybatis-plus3.0.1枚举返回为null解决办法

原来oracle的NUMBER类型在这个工具类里处理的时候,默认是BigDecimal类型,而我们在枚举类里定义的是Integer类型。

Objects.equals(Object a, Object b)


public static boolean equals(Object a, Object b) {
 return (a == b) || (a != null && a.equals(b));
}

所以在判断是否逻辑一致的时候调用了Integer数值的equals方法,也就是


//false
log.info(new Integer(6).equals(new BigDecimal(6)));

解决办法就很简单了,可以写一个Number的子类,重写一个业务逻辑一致的equals方法。当然最快速直接的就是把枚举类里的Integer改成BigDecimal类型。

修改后的枚举类:


package com.abc.common.model.enums;

import com.baomidou.mybatisplus.core.enums.IEnum;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

import java.math.BigDecimal;

/**
* 字段类型枚举
* @author huangsz
* @version 1.0
* @date 2020/10/22 11:01
*/
@Getter
public enum FieldType implements IEnum<BigDecimal> {
 NONE(new BigDecimal(-1), ""),
 NORMAL_INPUT(new BigDecimal(0), "文本"),
 BIG_INPUT(new BigDecimal(1), "多文本"),
 DATETIME(new BigDecimal(2), "日期时间"),
 DATE(new BigDecimal(3), "日期"),
 TIME(new BigDecimal(4), "时间"),
 UPLOAD(new BigDecimal(5), "文件上传"),
 DICT(new BigDecimal(6), "字典");

private final BigDecimal value;

@JsonValue
 private final String fieldType;

private static final FieldType[] values = values();

FieldType(BigDecimal value, String fieldType) {
   this.value = value;
   this.fieldType = fieldType;
 }

@JsonCreator
 public static FieldType valueOf(BigDecimal value) {
   for (FieldType enu : values) {
     if (enu.getValue().equals(value)) {
       return enu;
     }
   }
   return null;
 }
}

mybatis-plus3.0.1枚举返回为null解决办法

这回出现了,问题解决

来源:https://blog.csdn.net/SakuyaM/article/details/109329958

标签:mybatis-plus,枚举,返回null
0
投稿

猜你喜欢

  • Java字符串驼峰与下换线格式转换如何实现

    2022-02-18 09:56:14
  • Java异步调用转同步方法实例详解

    2023-11-01 20:38:25
  • springboot返回前端中文乱码的解决

    2023-08-09 11:49:12
  • C#之set与get方法的用法案例

    2021-08-09 01:17:18
  • Android获得所有存储设备位置的最佳方法

    2022-06-27 21:08:51
  • seata springcloud整合教程与遇到的坑

    2023-09-19 03:11:06
  • C语言实现简单弹跳小球

    2022-07-03 12:54:34
  • C语言实现贪吃蛇游戏演示

    2023-07-03 14:16:43
  • SpringBoot 实现动态添加定时任务功能

    2022-07-12 05:07:40
  • Android学习笔记-保存数据到SQL数据库中(Saving Data in SQL Databases)

    2023-07-28 08:32:20
  • Android串口通讯SerialPort的使用详情

    2022-03-08 00:23:46
  • 详解Android Handler的使用

    2022-11-17 12:59:18
  • 从字符串中截取等长字节的Java代码

    2023-03-12 10:11:41
  • Android SharedPreferences四种操作模式使用详解

    2021-06-06 00:15:08
  • Android TextWatcher三个回调以及监听EditText的输入案例详解

    2022-06-04 10:22:29
  • Jar包冲突问题原理及解决方案

    2023-03-05 09:40:02
  • Android仿微信单击拍照长按录像功能实例代码

    2022-01-16 17:45:07
  • Springboot工具类FileCopyUtils使用教程

    2023-10-15 18:56:36
  • 快速定位Java 内存OOM的问题

    2022-05-26 00:19:38
  • Android自定义Spinner下拉列表(使用ArrayAdapter和自定义Adapter实现)

    2021-08-13 16:34:16
  • asp之家 软件编程 m.aspxhome.com