mybatis-plus中的in的使⽤,是传Array?还是传List?别再纠结了springboot项⽬通常配合mybatisplus来做数据CRUD。
我们在查询或更新数据的时候,有时要⽤到in来过滤数据。⽐如
SELECT * FROM emax_scbg_order WHERE order_no IN (1305679009380433922,1305405259472830465)
mybatisplus中关于in⽅法的使⽤,在传多个字段值的时候,我们经常搞不清是传Array呢还是ArrayList呢?
其实,细⼼的同学,看⼀下in⽅法的定义,就明⽩了。
mybatisplus中有4个in⽅法的重载。
所有Wrapper的超类是AbstractWrapper,AbstractWrapper实现了Func<Children, R>接⼝。in⽅法主要在Func<Children, R>接⼝中定义。
下⾯是Func<Children, R>接⼝中in⽅法的4个重载:
//mybatis-plus-core-3.1.2.jar
package ditions.interfaces;
/**
* 查询条件封装
springboot其实就是spring*
* @author hubin miemie HCL
* @since 2017-05-26
*/
@SuppressWarnings("unchecked")
public interface Func<Children, R> extends Serializable {
/**
* ignore
*/
default Children in(R column, Collection<?> coll) {
return in(true, column, coll);
}
/**
* ignore
*/
default Children in(R column, values) {
return in(true, column, values);
}
/
**
* 字段 IN (v0, v1, ...)
* <p>例: in("id", 1, 2, 3, 4, 5)</p>
*
* <li> 如果动态数组为 empty 则不会进⾏ sql 拼接 </li>
*
* @param condition 执⾏条件
* @param column    字段
* @param values    数据数组
* @return children
*/
default Children in(boolean condition, R column, values) {
return in(condition, column, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{}))
.collect(toList()));
}
/**
* 字段 IN ((0), (1), ...)
* <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
*
* <li> 如果集合为 empty 则不会进⾏ sql 拼接 </li>
*
* @param condition 执⾏条件
* @param column    字段
* @param coll      数据集合
* @return children
*/
Children in(boolean condition, R column, Collection<?> coll);
}
我们可以看到,in⽅法接收字段值的⽅式,⼀种是,⼀种是Collection<?>。
■ Collection<?>不⽤说了,是集合,⽐如Listt<E>、Sett<E>、Queuet<E>等。
■ 是可变长参数(可变参数),可变长参数本质上就是⼀个数组,既可以接收⼀个或多个离散的值,也可以接收数组对象。也就是说,in⽅法同时⽀持传⼊数组和集合。取决于你调⽤哪个重载⽅法。
使⽤in的姿势
正确姿势⼀(List集合):
List<Long> ids = Arrays.asList(122L,23L);;
new QueryWrapper<Driver>().lambda().in(Driver::getServiceId,ids);
正确姿势⼆(数组对象):
Long[] ids={1305679009380433922,1305679009380433922};
LambdaQueryWrapper<Driver> queryWrapper = new QueryWrapper<Driver>().lambda().in(Driver::getServiceId,ids);
正确姿势三(离散值):
new QueryWrapper<Driver>().lambda()
.in(Driver::getServiceId,1305679009380433922,1305679009380433922);
正确结果:
==>  Preparing: SELECT*FROM emax_scbg_order WHERE order_no IN (?,?)
==> Parameters: 1305679009380433922(String), 1305405259472830465(String)
<==      Total: 2
千万别传模棱两可的参数,这样jvm会给你意想不到的结果。
错误姿势⼀:
.in(
StringUtils.OrderNumList()),
ScbgOrder::getOrderNo,
StringUtils.OrderNumList()) ? vo.getOrderNumList().split(",") : "");
错误结果⼀:
==> Preparing: SELECT * FROM emax_scbg_order WHERE order_no IN (?)
==> Parameters: [Ljava.lang.String;@3eb6d7a9(String[])
<== Total: 0
调试程序可以看到values⾥的参数值:
错误姿势⼆:
.in(StringUtils.OrderNumList()),ScbgOrder::getOrderNo,"123,4566");
错误结果⼆:
==> Preparing: SELECT * FROM emax_scbg_order WHERE order_no IN (?)
==> Parameters: 1,3(String)
<== Total: 0
OK,那么not in怎么⽤呢?
在mybatisplus中,not in的⽤法与in是相同的。如下notIn⽅法签名的截图⼀看便知:
话外:调⽤in出现NullPointerException,why?
下⾯代码执⾏到第9⾏时,抛出空指针异常。可以看出来,这个in重载是public Children in(boolean condition, R column, values)。开发同学疑惑:明明这个in的第⼀个
参数判断vo.getOprationType()是否为空了呀,为空就不执⾏后⾯的第三个参数了,不为空才会执⾏后⾯的逻辑呀。那么,即使vo.getOprationType()为null,也不应该会抛空指针呀!
1private LambdaQueryWrapper<PayMerchantOpenFlow> getPayMerchantOpenFlowQueryWrapperByVO(PayMerchantOpenFlowDTO vo){
2    LambdaQueryWrapper<PayMerchantOpenFlow> wrapper = new QueryWrapper<PayMerchantOpenFlow>().lambda()
3            .eq(StringUtils.MerchantCode()), PayMerchantOpenFlow::MerchantCode())
4            .eq(null != vo.getRelationId(), PayMerchantOpenFlow::RelationId())
5            .eq(StringUtils.Status()), PayMerchantOpenFlow::Status())
6            .eq(StringUtils.MerchantName()), PayMerchantOpenFlow::MerchantName())
7            .eq(StringUtils.PayChannelCode()), PayMerchantOpenFlow::PayChannelCode())
8            .eq(StringUtils.PayChannelName()), PayMerchantOpenFlow::PayChannelName())
9            .in(StringUtils.OprationType()), PayMerchantOpenFlow::OprationType().split(","))
10            .between(StringUtils.CreateTimeBegin(), vo.getCreateTimeEnd()), PayMerchantOpenFlow::getCreateTime, vo.getCreateTimeBegin() + " 00:00:01", vo.getCreateTimeEnd() + " 23:59:59")
11            .orderByDesc(PayMerchantOpenFlow::getCreateTime);
12return wrapper;
13 }
答案是:上⾯的“第⼀个条件为true时才使⽤第三个参数执⾏sql处理”是in⽅法内部的逻辑,⽽不是调⽤⽅的逻辑。调⽤⽅所做的事情是把参数值传给in⽅法。所以,当

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。