溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mybatis-plus3.0.1枚舉返回空值如何解決

發(fā)布時間:2020-12-23 14:04:45 來源:億速云 閱讀:292 作者:Leah 欄目:開發(fā)技術(shù)

今天就跟大家聊聊有關mybatis-plus3.0.1枚舉返回空值如何解決,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

mybatis-plus 3.0.1 枚舉返回為null解決辦法

2020-11-02 14:28:48
今天再次回到代碼里無意間看到,原來和mybatis-plus沒有關系!發(fā)生這個問題的根本原因還是要看是否在對應的Mapper.xml里指定了jdbcType。由于我使用了IDEA的代碼生成插件,所以沒有再進一步去研究為什么返回的數(shù)據(jù)類型會是以BigDecimal包裝的,就此鬧了個笑話。。

結(jié)論:枚舉類用EnumValue注解修飾的數(shù)據(jù)類型,例如是Integer,那么在Mapper.xml中的jdbcType需要修改為對應類型!

最好的解決辦法就是使用新版的mybatis-plus!

3.1.0版本后改變了mybatis原生的默認行為,而3.1.2版本以下的枚舉處理類依然是EnumTypeHandler。推測在3.1.2以上的版本應該是不會出現(xiàn)這個問題的。

項目環(huán)境:springboot + oracle + mybatis-plus

實體類引用到的枚舉類,實現(xiàn) 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是沒有作用的。至于為什么不更新,項目是多人協(xié)同開發(fā)的,公司也不允許私自修改依賴包。

調(diào)用接口查詢時問題出現(xiàn)了:

mybatis-plus3.0.1枚舉返回空值如何解決

日志說明這個字段是有一個有效值的,并且查詢出來了。(FIELD_TYPE字段是NUMBER(1)類型)

mybatis-plus3.0.1枚舉返回空值如何解決

6對應的枚舉值應該是DICT,也就是字典類型才對,但是映射到實體類時卻變成了NULL。

在我看了一下午的源碼以后發(fā)現(xiàn)了問題的原因:
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用來處理數(shù)值和枚舉類之間關系的處理類(這里如果枚舉類是用@EnumValue來標注數(shù)值的話,處理類是相同包結(jié)構(gòu)下的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;
  }
}

理解了源碼就發(fā)現(xiàn)了問題所在了,讓這個EnumUtils返回null值的情況,大概是Objects.equals()判斷值是否相等時,找不到這個枚舉類里面有任何和查詢出來的值相同的值。

mybatis-plus3.0.1枚舉返回空值如何解決

原來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));
}

所以在判斷是否邏輯一致的時候調(diào)用了Integer數(shù)值的equals方法,也就是

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

解決辦法就很簡單了,可以寫一個Number的子類,重寫一個業(yè)務邏輯一致的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枚舉返回空值如何解決

這回出現(xiàn)了,問題解決

看完上述內(nèi)容,你們對mybatis-plus3.0.1枚舉返回空值如何解決有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI