MybatisPlus常用方法总结

关于MybatisPlus中常用方法与Wrapper使用总结

wrapper的in方法可以传入list

Wrapper 的 in 方法可以传入list对象

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public List<User> getUsersInIds(ArrayList<Long> userIds) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.in("id", userIds);
return userMapper.selectList(wrapper);
}
}

如果ArrayList里面是实体类,会自动匹配实体类中对应字段的属性吗?不会,我们需要转换为简单类型的list,可以用lambda+集合类快速转换

1
2
3
4
5
6
7
8
9
10
List<Order> orderList = new ArrayList<>();
Order order1 = new Order(1L, "order-001");
Order order2 = new Order(2L, "order-002");
orderList.add(order1);
orderList.add(order2);

List<Long> orderIdList = orderList.stream().map(Order::getId).collect(Collectors.toList());

QueryWrapper<Order> wrapper = new QueryWrapper<>();
wrapper.in("order_id", orderIdList);

wrapper查询某一个字段

在 MyBatis Plus 中,你可以使用 selectObjs 方法来单独查询某个字段的值。selectObjs 方法返回的是一个包含指定字段值的集合

以下是一个示例,假设你想单独查询 name 字段的值:

1
List<Object> nameList = yourMapper.selectObjs(Wrappers.<YourEntity>lambdaQuery().select(YourEntity::getName));

在这个示例中,yourMapper 是你的 Mapper 对象, YourEntity 是你的实体类。selectObjs 方法接受一个查询条件作为参数,这里使用了 Wrappers.<YourEntity>lambdaQuery().select(YourEntity::getName) 来指定查询条件。

.lambdaQuery() 创建了一个 LambdaQueryWrapper 对象,.select(YourEntity::getName) 指定了要查询的字段名。

查询结果将会返回一个包含 name 字段值的 List<Object> 集合。注意,如果查询返回的结果集为空,返回的集合可能是空的。

如果你的实体类有对应的 Mapper 类,你也可以直接使用 Mapper 类提供的方法进行查询,类似于下面的示例:

1
List<Object> nameList = yourMapper.selectObjs(new QueryWrapper<YourEntity>().select("name"));

在这个示例中,使用 QueryWrapper 对象进行查询,并通过 .select("name") 来指定要查询的字段名。

请根据你的具体代码和实际需求进行调整和修改。

如果你还有任何问题,请随时向我提问!

selectOne与selectObjs

selectOne查询一条记录,selectObjs只能查询多条。

在使用 MyBatis-Plus 进行查询操作时,selectOne 和 selectObj 两个方法,具有以下区别:

  1. selectOne:该方法用于查询符合条件的一条记录,并返回实体对象。如果符合条件的记录有多条或没有记录,则会抛出异常。(一般是这里要做出判断)。

    示例:

1
User user = userMapper.selectOne(wrapper);
  1. selectObj:该方法用于查询符合条件的一条记录,并返回该记录的单个字段值。如果符合条件的记录有多条或没有记录,则会返回 null

    示例:

1
Object field = userMapper.selectObj(wrapper);

总结来说,selectOne 适用于期望返回实体对象的场景,而 selectObj 则适用于仅需要获取一条记录的某个字段值的场景。通常情况下,当查询条件能够确保只返回一条记录时,两个方法可以互换使用,但根据方法的返回值类型来选择更加合适的方法可以提高代码的可读性和表达意图。

同时需要注意的是,这两个方法的查询条件都是基于所传入的 Wrapper 对象来确定的,Wrapper 对象中可以通过各种条件方法(如 eq、like、in 等)设置查询条件,具体根据你的需求来选择。

selectOne方法预防异常

需要预防两点:1. 没查到,后面调用值显示空指针。(判空)2. 查到了两个或更多条(limit 1)

在使用 selectOne 方法时,可以通过以下方式预防两种情况的发生:

  1. 没查到,后面调用值显示空指针:

    在使用 selectOne 方法后,可以首先判断返回的实体对象是否为 null,如果为 null,则可以进行相应的处理,避免后续调用出现空指针异常。例如,可以设置一个默认值来代替 null 值,或者抛出自定义的异常来进行处理。

    示例代码:

1
2
3
4
5
6
User user = userMapper.selectOne(wrapper);
if (user != null) {
// 实体对象不为 null,进行后续操作
} else {
// 实体对象为 null,进行处理
}
  1. 查到了两个或更多条:

    在使用 selectOne 方法时,如果查询到多个符合条件的记录,会抛出 TooManyResultsException 异常。为了避免该异常的发生,可以在查询前使用 limit 方法限制最多返回一条记录,泽民说不推荐使用limit1,如果查到了多条,我们要判断为什么会出现多条。

    示例代码:

1
2
3
4
5
6
7
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 设置查询条件
wrapper.eq("condition_column", condition);
// 设置限制返回记录数为1
wrapper.last("LIMIT 1");
User user = userMapper.selectOne(wrapper);
// 进行后续操作

怎么区分in和like

对于 in 方法,可以在查询条件中使用 in 方法进行批量查询。假设有一个 User 实体类,想要查询age在指定范围内的用户,可以使用 in 方法:

1
2
3
4
List<Integer> ages = Arrays.asList(20, 25, 30);
List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("age", ages));
//List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("字段名", 需要的值列表));

在上述代码中,我们使用 in 方法,在查询条件中指定了字段名和一个包含多个年龄值的集合,即可查询出符合条件的用户列表。

至于 like 方法,在 Mybatis-Plus 中也支持指定模糊查询条件。假设有一个 User 实体类,想要查询用户名中包含指定关键字的用户,可以使用 like 方法:

1
2
3
String keyword = "John"; //如果想查到JohnWaston
List<User> userList = userMapper.selectList(new QueryWrapper<User>().like("username", keyword));
//List<User> userList = userMapper.selectList(new QueryWrapper<User>().like("字段名", 待匹配的字符串));

在上述代码中,我们使用 like 方法,在查询条件中指定了字段名和一个关键字,即可查询出用户名中包含指定关键字的用户列表。

判断字符串startWith

mybatisplus怎么判断某个字段是不是startwith或者endwith,其实就是like。

  • like:左右两边都匹配
  • likeRight:对我们传入参数的右边进行匹配,我们传出的字符串应小于数据库的数据,相当于startWith方法
  • likeLeft:对我们传入参数的左边进行匹配,我们传出的字符串应小于数据库的数据,相当于endWith方法

将实体类传入wrapper构建

在构建wrapper时传入odd对象后,会根据 odd 对象的非空字段来构建查询条件。具体来说,如果 odd 对象的某个字段的值不为空,则 QueryWrapper 将会生成一个等于(=)该字段值的查询条件;如果 odd 对象的某个字段的值为空,则不会生成该字段的查询条件。

1
QueryWrapper<Odd> wrapper = new QueryWrapper<Odd>(odd);

注意:这里是构建的全等条件,如果有其他的比如like或者大于小于,需要额外进行判断。

纯wrapper版本的子查询

当查询某个表的数据时,可能会有其他的表的id的字段,但是我们需要将关联表的id查询出来,我该怎么只通过wrapper进行查询?

实体类中额外的属性

1
2
@TableField(exist = false)
private String pwrDeviceName;

wrapper构建子查询

1
2
3
4
5
6
@Override
public List<PwrConnector> selectList(PwrConnector pwrConnector) {
QueryWrapper<PwrConnector> wrapper = new QueryWrapper<>(pwrConnector);
wrapper.select("pwr_connector.*,(select name from pwr_device pd where pd.pwr_device_id = pwr_connector.pwr_device_id) as pwrDeviceName");
return pwrConnectorMapper.selectList(wrapper);
}

总结:

  1. 通过select * 加上括号子查询,查询出数据库字段和我们设置的额外字段
  2. 在实体类中的额外字段与sql查询出来的额外字段对应上

UpdateWrapper

方式一(UpdateWrapper 条件构造器)

1
2
3
4
5
6
7
8
9
10
// 根据userName修改
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("userName","一个肥鲶鱼");

User user = new User();
user.setSex("男");

userMapper.update(user, updateWrapper);
// sql等于是:
// update user set sex = '男' where userName = '一个肥鲶鱼'

方式二(适用于少量字段的更新,避免构造实体对象)

1
2
3
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("userName","一个肥鲶鱼").set("sex", "男");
userMapper.update(null, updateWrapper);

方式三(Lamda构造器)

1
2
3
4
5
LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(User::getUserName, "一个肥鲶鱼")
.set(User::getSex, "男")
.set(User::getAge, 18);
userMapper.update(null, lambdaUpdateWrapper);

云海项目中的分页操作

云海项目不需要自己对分页参数进行设置,他会自动拦截到分页参数。

Controller

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 查询动力网端子——列表
* @author zhangrui
* @date 2024/1/11 17:00
* @param pwrConnector
* @return TableDataInfo
*/
@PostMapping("/page")
public TableDataInfo page(@RequestBody PwrConnector pwrConnector) {
startPage();
List<PwrConnector> list = pwrConnectorService.selectList(pwrConnector);
return getDataTable(list);
}

当你懒得创建wrapper对象

错误示范:无法从 static 上下文引用非 static 方法

1
2
List<SpcRoom> spcRoomList = spcRoomMapper.selectList(new LambdaQueryWrapper<>()
.eq(SpcRoom::getStationId, spcStationId));

正确示范,需要加上泛型

1
2
List<SpcRoom> spcRoomList = spcRoomMapper.selectList(new LambdaQueryWrapper<SpcRoom>()
.eq(SpcRoom::getStationId, spcStationId));

new LambdaQueryWrapper() 代码中没有指明泛型,导致编译器无法识别 selectList() 方法所对应的实体类型。

多表联查还是selectOne?

selectOne写代码更方便

如果只是简单的需求的话我们可以直接一步一步的跟着mybatisPlus走,一个对象接着一个对象的查询

多表联查效率更高

如果数据表的量比较大,同时我们要查的不是单个对象而是一个列表。这时如果涉及到优化查询速度,我们就应该想办法通过leftjoin去进行一次性查询。尽量将对数据库的请求降到最小。


MybatisPlus常用方法总结
http://wahoyu.xyz/2023/12/14/MybatisPlus/
作者
Wahoyu
发布于
2023年12月14日
许可协议