一.条件构造器
我们前面使用的MP功能主要是根据id进行操作的,并未涉及到复杂查询。而根据id所进行的增删改查操作在MP中都有直接的封装。但是遇到复杂的查询条件时,如何使用MP进行操作是我们要考虑的问题。因此MP为我们提供了条件构造器。

在BaseMapper接口中有很多Wrapper接口。这些Wrapper接口就是用来指定复杂查询条件的。AbstractWrapper中实现了很多复杂条件的sql语句查询。

eq:等于。ne:不等于。gt:大于。ge:大于等于。lt:小于。le:小于等于。like:模。也就是说复杂的where条件AbstractWrapper都能帮助我们构造。
我们关注下面的两个子类UpdateWrapper和QueryWrapper。这两个子类除了继承AbstractWrapper,也可以构造复杂where语句外,在此基础上扩展了相关的功能。如QueryWrapper用于查询时,不仅可以用来构建复杂where语句,还可以进行select功能,指定要查询的select字段(select column1, column2 ... from ... where ...)。
UpdateWrapper扩展了set部分,除了可以定义复杂where语句外,还可以设置set语句条件。可以使用setSql,在该方法里面使用字符串编写set条件,直接拼入sql语句中。

这个在特殊场景下会用到,但比较少见。
综上,UpdateWrapper和QueryWrapper就是在AbstractWrapper的基础上做了拓展。
除了这些还有对应的Lambda,这些LambdaUpdateWrapper和LambdaQueryWrapper功能上与上面的一样,只是使用了Lambda表达式。
二.案例演示
1.QueryWrapper


@Testvoid testQueryByQueryWrapper() {QueryWrapper<User> queryWrapper = new QueryWrapper<User>().select("id","username","info","balance").like("username","o").ge("balance",1000);userMapper.selectList(queryWrapper);}// 将Jack的余额设置为2000@Testvoid testUpdateByQueryWrapper() {// 1.要更新的数据User user = new User();user.setBalance(2000);// 2.更新的条件QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("username","Jack");// 3.执行更新userMapper.update(user,queryWrapper);}
QueryWrapper可以支持链式编程,在第一个演示案例中我们除了定义复杂的查询语句外,还使用QueryWrapper来指定要查询的字段。通过其中的select方法来指定。
在第二个演示案例中我们要指定更新的数据,即创建一个User对象并将余额设置为2000。然后使用QueryWrapper来定义复杂的查询语句并执行更新。
因为是查询语句,且查询出来的是一个列表,因此使用selectList进行查询。并将QueryWrapper对象传入。
2.UpdateWrapper

void testUpdateQuery() {List<Long> ids = List.of(1L,2L,4L);// 1.构造Wrapper对象UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>().setSql("balance = balance - 200").in("id",ids);// 2.执行更新操作。由于这次每个用户余额均不相同,因此无法创建对象来指定余额值,且每个用户余额不同,因此要使用updateWrapper的setSql动态拼接sql语句,且在updateWrapper中指定要操作的数据类型userMapper.update(null,updateWrapper);}
这个情况比较特殊,由于这次每个用户余额均不相同,因此无法创建对象来指定余额值,且每个用户余额不同,因此要使用updateWrapper的setSql动态拼接sql语句,且在updateWrapper中指定要操作的数据类型。
sql语句要使用in,因此要构建一个集合来封装id。
在这里由于是根据不同User动态更新,因此使用setSql指定更新条件为balance = balance - 200。
三.Lambda表达式
我们上边的代码在指定字段时都是硬编码,即直接将字段名写死。这样不好因此我们要使用软编码。这就要使用Lambda表达式。
// 查询出名字带o的,存款大于等于1000元的id,username,info,balance字段@Testvoid testLambdaQueryByQueryWrapper() {LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>().select(User::getId,User::getUsername,User::getInfo,User::getBalance).like(User::getUsername,"o").ge(User::getBalance,1000);userMapper.selectList(queryWrapper);}// 将Jack的余额设置为2000@Testvoid testUpdateByLambdaQueryWrapper() {// 1.要更新的数据User user = new User();user.setBalance(2000);// 2.更新的条件LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>().eq(User::getBalance,"Jack");// 3.执行更新userMapper.update(user,queryWrapper);}// 将用户id为1,2,4的用户余额减200@Testvoid testLambdaUpdateQuery() {List<Long> ids = List.of(1L,2L,4L);// 1.构造Wrapper对象LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<User>().setSql("balance = balance - 200").in(User::getId,ids);// 2.执行更新操作。由于这次每个用户余额均不相同,因此无法创建对象来指定余额值,且每个用户余额不同,因此要使用updateWrapper的setSql动态拼接sql语句,且在updateWrapper中指定要操作的数据类型userMapper.update(null,updateWrapper);}
使用Lambda表达式,将字段换为查询对象::get方法,利用反射来获取字段。
