Mybatis-Plus官方文档:https://baomidou.com/pages/10c804/
本文主要讨论Mybatis-Plus条件构造器的区别和用法
以 Query* 为例:
// 创建QueryWrapper
QueryWrapper queryWrapper1 = Wrappers.query();
QueryWrapper queryWrapper2 = new QueryWrapper();
// 创建LambdaQueryWrapper
LambdaQueryWrapper lambdaQueryWrapper1 = Wrappers.query().lambda();
LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper().lambda();
// 创建QueryChainWrapper
QueryChainWrapper<User> userQueryChainWrapper = ChainWrappers.queryChain(userMapper);
// 创建LambdaQueryChainWrapper
LambdaQueryChainWrapper<User> userLambdaQueryChainWrapper = ChainWrappers.lambdaQueryChain(userMapper);
带 lambda 的 wrapper 进行列名匹配时,使用的是 Lambda 的语法,属于函数式编程,偏向于对象。反之不带lambda的就需要手动指定列名(即进行硬编码数据库中的字段名)
不带 chain 的 wrapper(QueryWrapper、lambdaQueryWrapper等)执行时,需要将封装的 wrapper 提供给 Mapper,调用Mapper的方法,才可以使用。而带 chain 的 wrapper (QueryChainWrapper、LambdaQueryChainWrapper等)可以直接链式调用数据执行操作的方法
根据条件查询列表
// 1.几乎不会使用这种方法,局限很大
HashMap<String, Object> map = new HashMap<>();
map.put("1", "12");
userMapper.selectByMap(map);
// 2.QueryWrapper条件用法
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.like("email", "24252") //模糊查询
.between("age", 20, 22)
.or()
.eq("name", "zcx")
.orderByAsc("age") //升序
.last("limit 0,3"); //last用法:在sql末尾添加sql语句,有sql注入风险
List<User> list = userMapper.selectList(wrapper);
// 3.使用lambda
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>()
.like("email", "24252") //模糊查询
.between(User::getAge, 20, 22)
.eq("name", "zcx")
.orderByAsc(User::getAge);
List<User> list = userMapper.selectList(lambdaQueryWrapper);
// 4.使用lambda以及链式
LambdaQueryChainWrapper<User> lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(userMapper)
.like("email", "24252") //模糊查询
.between(User::getAge, 20, 22)
.eq("name", "zcx")
.orderByAsc(User::getAge);
List<User> list = lambdaQueryChainWrapper.list();
根据条件更新
// 根据id更新
User user = new User();
user.setUserId(1);
user.setAge(18);
Integer rows = userMapper.updateById(user);
// 1.构造实体对象来更新
User user = new User();
user.setAge(18);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "susan");
Integer rows = userMapper.update(user, updateWrapper);
// 2.条件构造器Set方法来更新
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name","susan").set("age", 18);
Integer rows = userMapper.update(null, updateWrapper);
// 3.使用lambda
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getName, "susan").set(User::getAge, 18);
Integer rows = userMapper.update(null, lambdaUpdateWrapper);
// 4.使用lambda以及链式
LambdaUpdateChainWrapper<User> lambdaUpdateChainWrapper = new LambdaUpdateChainWrapper<>(userMapper);
boolean update = lambdaUpdateChainWrapper.eq(User::getName, "susan").set(User::getAge, 18).update();
实体bean
@Data
public class CallLogForm {
@ApiModelProperty(value = "开始时间")
private LocalDateTime beginTime;
@ApiModelProperty(value = "结束时间")
private LocalDateTime endTime;
@ApiModelProperty(value = "调用方")
private String client;
@ApiModelProperty(value = "被调用方")
private String server;
@ApiModelProperty(value = "接口名称")
private String interName;
@ApiModelProperty(value = "状态 0失败 1成功")
private String status;
}
开始
LambdaQueryWrapper<CallLog> wrapper = new LambdaQueryWrapper<CallLog>()
.eq(StringUtils.isNotEmpty(form.getClient()), CallLog::getClient, form.getClient())
.eq(StringUtils.isNotEmpty(form.getServer()), CallLog::getServer, form.getServer())
.ge(form.getBeginTime() != null, CallLog::getOperateDate, form.getBeginTime())
.lt(form.getEndTime() != null, CallLog::getOperateDate, form.getEndTime().plusDays(1))
.like(StringUtils.isNotEmpty(form.getInterName()), CallLog::getInterName, form.getInterName())
.eq(StringUtils.isNotEmpty(form.getStatus()), CallLog::getStatus, form.getStatus());
List<CallLog> list = callLogDao.selectList(wrapper);
注意,下面这个条件构造其实是有问题
.lt(form.getEndTime() != null, CallLog::getOperateDate, form.getEndTime().plusDays(1))
这里,因为对 form.getEndTime()
进行了加1天的操作。刚开始以为前面的为空判断会让程序跳过这个条件构造,但实际上代码判定之前会先执行 form.getEndTime().plusDays(1)
,这样就导致会出现空指针异常。
这里有两种解决办法
可以分步写,手动判断空后,再拼接条件构造
LambdaQueryWrapper<CallLog> wrapper = new LambdaQueryWrapper<CallLog>()
.eq(StringUtils.isNotEmpty(form.getClient()), CallLog::getClient, form.getClient())
.eq(StringUtils.isNotEmpty(form.getServer()), CallLog::getServer, form.getServer())
.like(StringUtils.isNotEmpty(form.getInterName()), CallLog::getInterName, form.getInterName())
.eq(StringUtils.isNotEmpty(form.getStatus()), CallLog::getStatus, form.getStatus());
if (form.getBeginTime() != null) {
wrapper.ge(form.getBeginTime() != null, CallLog::getOperateDate, form.getBeginTime());
}
if (form.getEndTime() != null) {
wrapper.lt(form.getEndTime() != null, CallLog::getOperateDate, form.getEndTime().plusDays(1));
}
List<CallLog> list = callLogDao.selectList(wrapper);
可以对 form.getEndTime().plusDays(1)
进行改写,避免因为空指针异常导致程序错误,比如封装工具类等,封装也比较简单,这里就不展示代码了
ps,个人感觉这两种方法都不是很好,目前没有更好的方法,之后再更新文章吧。