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

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是没有作用的。至于为什么不更新,项目是多人协同开发的,公司也不允许私自修改依赖包。

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

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

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()判断值是否相等时,找不到这个枚举类里面有任何和查询出来的值相同的值。

原来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解决办法的文章就介绍到这了,更多相关mybatis-plus枚举返回null内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mybatis-plus使用@EnumValue处理枚举类型的示例代码

    自mybatis3.1.0开始,如果你无需使用原生枚举,可配置默认枚举来省略扫描通用枚举配置 默认枚举配置 1.配置文件配置枚举所在的包 #配置枚举 支持通配符 * 或者 ; 分割 mybatis-plus.type-enums-package=com.iscas.biz.mp.test.model.enums mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHa

  • Mybatis-Plus通用枚举的使用详解

    解决了繁琐的配置,让 mybatis 优雅的使用枚举属性! 修改表结构 ALTER TABLE `tb_user` ADD COLUMN `sex` INT ( 1 ) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`; 定义枚举 public enum SexEnum implements IEnum<Integer> { MAN(1, "男"), WOMAN(2, "女"); private int v

  • 详解mybatis-plus使用@EnumValue注解的方式对枚举类型的处理

    前言: 在开发中,我们经常会用到诸如:性别(男/女).审核状态(未审核/审核中/已审核)之类的数据,通常会在数据库中使用一个数字类型的字段来标识,比如:性别,用1来表示男,2来表示女,而在代码中一般会定义成enum类型或静态常量来避免在业务代码中出现"0/1"这种魔法值,但是在数据库存储及前后端交互的时候,就需要进行转化:无论是在SQL.前端还是后台转化,都需要写相应的代码,无形中增加了开发工作量:mybatis-plus实现了对该问题的处理,能够让我们在查询数据库时,直接能够返回字段

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

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

  • Android在view.requestFocus(0)返回false的解决办法

    我们有时候想让listview的第一行自动获取到焦点,我们就会使用view.requestFocus(0)来操作,而有时候并不生效,debug后显示rerurn为false. 这是因为我们获取焦点太早,listview控件还为加载完毕.可以尝试一下方法解决: listview.post(new Runnable(){ @Override public void run(){ view.requestFocus(0); } }); 以上所述是小编给大家介绍的Android在view.request

  • 详解php中curl返回false的解决办法

    首先来看一个封装的curl函数 function request_post($url = '', $param = '') { if (empty($url) || empty($param)) { return false; } $postUrl = $url; $curlPost = $param; $curl = curl_init();//初始化curl curl_setopt($curl, CURLOPT_URL,$postUrl);//抓取指定网页 curl_setopt($curl

  • Mybatis报错: org.apache.ibatis.exceptions.PersistenceException解决办法

    Mybatis报错: org.apache.ibatis.exceptions.PersistenceException解决办法 一.问题描述 写好配置文件用JUnit进行测试,一运行就报错: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: org.apache.ibatis.reflection.ReflectionException: Error instantiat

  • Java提示缺少返回语句的解决办法

    Java提示缺少返回值语句怎么办?这里我们给大家提供具体的解决方法. 首先,以下面的程序为例,会看到在控制台有:错误:缺少返回语句的提示. 找到类中定义的方法test中发现,明明已经定义了return,软件依然会提示错误. 将return定义到for循环之外,就会发现,程序不再报错. 原因是因为数组不仅仅可以存放具体的变量值,而且可以不赋给数组任何值. 在数组内容为空的情况,程序是没有报错的,所以需要将return返回值定义到   for 循环之外即可. 关于Java中return缺少返回语句的

  • 详解Spring关于@Resource注入为null解决办法

    初学spring,我在dao层初始化c3p0的时候,使用@Resource注解新建对象是发现注入为null,告诉我 java.lang.NullPointerException. @Repository public class UserDaoImpl implements UserDao { @Resource ComboPooledDataSource dataSource; 反复检查了配置文件,没有发现任何问题,最后在同学的帮助下终于发现了问题的所在,特记录于此,一个教训. 问题就出在我的

  • 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序报错的解决办法

    错误描述: 在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错: "未在本地计算机上注册"microsoft.ACE.oledb.12.0"提供程序" 代码示例: static void Main(string[] args) { readexcel("D:\\test\\xlsxtest.xlsx"); } public static void readexcel(string _path) { Da

  • ImageMagickObject获取图片的信息无返回值的解决办法

    通过ImageMagickObject的identify获取图片的信息,在命令行下好用,但是放到程序里就得不到返回值,经过实践发现只能使用format参数进行格式化后才能返回数据. 复制代码 代码如下: SET oImg = Server.CreateObject("ImageMagickObject.MagickImage.1") vReturn = oImg.identify("-format","%m,%hx%w","c:\sha

  • Serv-U 无法连接到服务器127.0.0.1,端口43958 之解决办法

    Serv-U"无法连接到服务器127.0.0.1,端口43958"的原因 始终搞不明白问题出在哪里,后上网查了资料,大概原因如下: 43958,这是Serv-U的本地管理端口,只允许127.0.0.1连接,这个端口不能连接,是因为: 1. 权限错.(本人再将system加进,且赋予默认权限,问题解决.) 2. 可能软件本身问题,也禁止了127.0.0.1的连接: 3. 黑客攻击也有可能出现这个问题. Serv-U"无法连接到服务器127.0.0.1,端口43958"

  • 浅谈mysql8.0新特性的坑和解决办法(小结)

    一.创建用户和授权 在mysql8.0创建用户和授权和之前不太一样了,其实严格上来讲,也不能说是不一样,只能说是更严格,mysql8.0需要先创建用户和设置密码,然后才能授权. #先创建一个用户 create user 'hong'@'%' identified by '123123'; #再进行授权 grant all privileges on *.* to 'hong'@'%' with grant option; 如果还是用原来5.7的那种方式,会报错误: grant all privi

随机推荐