Mybatis-Plus条件构造器笔记

Mybatis-Plus条件构造器笔记

Mybatis-Plus官方文档:https://baomidou.com/pages/10c804/

本文主要讨论Mybatis-Plus条件构造器的区别和用法

  • QueryWrapper、UpdateWrapper
  • lambdaQueryWrapper、LambdaUpdateWrapper
  • QueryChainWrapper、UpdateChainWrapper
  • LambdaQueryChainWrapper、LambdaUpdateChainWrapper

创建Wrapper

以 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);

Wrapper区别

  • 带 lambda 的 wrapper 进行列名匹配时,使用的是 Lambda 的语法,属于函数式编程,偏向于对象。反之不带lambda的就需要手动指定列名(即进行硬编码数据库中的字段名)

  • 不带 chain 的 wrapper(QueryWrapper、lambdaQueryWrapper等)执行时,需要将封装的 wrapper 提供给 Mapper,调用Mapper的方法,才可以使用。而带 chain 的 wrapper (QueryChainWrapper、LambdaQueryChainWrapper等)可以直接链式调用数据执行操作的方法

Wrapper用法

Query操作

根据条件查询列表

条件构造器
// 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();

Update操作

根据条件更新

简单更新
// 根据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();

问题记录

使用 LambdaQueryWrapper 动态添加过滤条件

实体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) ,这样就导致会出现空指针异常

这里有两种解决办法

  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);
    
  2. 可以对 form.getEndTime().plusDays(1) 进行改写,避免因为空指针异常导致程序错误,比如封装工具类等,封装也比较简单,这里就不展示代码了

ps,个人感觉这两种方法都不是很好,目前没有更好的方法,之后再更新文章吧。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值