mybatis-plus集合判空避坑

昨天发现一个鬼畜问题,测试环境和生产的配置互换后,测试后把环境切换回测试就一直报错,原因是用户表中生的一个用户生成了两个openId,getOne后报错,于是做出了一些改变:

QueryWrapper wrapper = new QueryWrapper().eq("openid",
					loginResult.getOpenid());
MiniproUser user = this.list(wrapper) == null?null:this.list(wrapper).get(0);

把原来的getOne()改为了list,有数据取第一条,结果偏偏集合判空这里出了,如果用户不存在,走到这行代码直接抛异常。这里对OpenId重新设置下,模拟新用户注册的情况:

mybatis-plus集合判空避坑_第1张图片

 mybatis-plus集合判空避坑_第2张图片

 结果发现成勋直接跳到了catch代码块并抛出:java.lang.IndexOutOfBoundsException: Index: 0, Size: 0

有说法是:

实体类使用了@Builder注解,则无法使用无参构造函数,最终导致mybatis在创建实体时报错

在实体类加上@NoArgsConstructor和@AllArgsConstructor即可使用无参构造函数(来源:Mybatis查询报IndexOutOfBoundsException - 博客 - 编程圈)

但是我确实使用了@Builder,但是也已经添加了@NoArgsConstructor和@AllArgsConstructor:

mybatis-plus集合判空避坑_第3张图片

微微一笑发现问题并没有那么简单,既然直接判空集合不行,用工具类试试,然后调试进入看一下:

于是进行改造如下:

MiniproUser user = ObjectUtils.isEmpty(this.list(wrapper))?null:this.list(wrapper).get(0);

进入isEmpty()调试发现:

/**
	 * Determine whether the given object is empty.
	 * 

This method supports the following object types. *

    *
  • {@code Optional}: considered empty if {@link Optional#empty()}
  • *
  • {@code Array}: considered empty if its length is zero
  • *
  • {@link CharSequence}: considered empty if its length is zero
  • *
  • {@link Collection}: delegates to {@link Collection#isEmpty()}
  • *
  • {@link Map}: delegates to {@link Map#isEmpty()}
  • *
*

If the given object is non-null and not one of the aforementioned * supported types, this method returns {@code false}. * @param obj the object to check * @return {@code true} if the object is {@code null} or empty * @since 4.2 * @see Optional#isPresent() * @see ObjectUtils#isEmpty(Object[]) * @see StringUtils#hasLength(CharSequence) * @see StringUtils#isEmpty(Object) * @see CollectionUtils#isEmpty(java.util.Collection) * @see CollectionUtils#isEmpty(java.util.Map) */ @SuppressWarnings("rawtypes") public static boolean isEmpty(@Nullable Object obj) { if (obj == null) { return true; } if (obj instanceof Optional) { return !((Optional) obj).isPresent(); } if (obj instanceof CharSequence) { return ((CharSequence) obj).length() == 0; } if (obj.getClass().isArray()) { return Array.getLength(obj) == 0; } if (obj instanceof Collection) { return ((Collection) obj).isEmpty(); } if (obj instanceof Map) { return ((Map) obj).isEmpty(); } // else return false; }

第一个if判断obj竟然不是null,查看堆栈信息,发现里边是一个LinkedList,而且内部还有Map,存放有框架和mybatis的一些东西,猜想是一个返回数据集的附加信息,但是没有真正需要的数据在里边,因此,为了保险起见,改成

ObjectUtils.isEmpty(this.list(wrapper))
或者
this.list(wrapper).size == 0

经过测试两者都可以。

总结:在使用框架或者封装第三方的工具时,对于一些常见的集合操作或者判断操作,还是谨慎选择,因为经过层层封装后的对象,你不知道里边带了究竟有多少其他的东西,很可能会给出错误的结果。

你可能感兴趣的:(编码,原理,框架,java-ee,spring,mybatis-plus)