问题展现:
TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2] with root cause
分析过程
我的EmployeeService接口继承了IService接口,查看IService接口中的getOne方法,注意这里throEx参数为true
最终都是调用 T getOne(Wrapper<T> queryWrapper, boolean throwEx);
ServiceImpl实现该接口
this.baseMapper.selectOne(queryWrapper):返回单个对象
SqlHelper.getObject():返回查询到的集合中的首个对象
对其中getOne方法解释(重点)
boolean throwEx:用于控制当查询结果为空时是否抛出异常。
this.baseMapper.selectOne(queryWrapper):当有异常时,找到baseMapper接口 中的selectOne()方法查询,得到符合条件的单个结果SqlHelper.getObject(this.log, this.baseMapper.selectList(queryWrapper)):throwEx 参数为 false 时执行。SqlHelper 是 MyBatis-Plus 提供的一个帮助类,用于辅助数据库操作。SqlHelper.getObject 方法用于从查询结果列表中获取第一个元素,即符合条件的一条数据。
结论
当使用getOne(queryWrapper)时,throwEx被设置为true交给 T getOne(Wrapper<T> queryWrapper, boolean throwEx)处理 接着其实现类ServiceImpl判断throwEx为true,则执行this.baseMapper.selectOne(queryWrapper) 但我并未给queryWrapper 添加查询条件,所以查询时会返回数据库中所有数据 seleectOne()方法设计用于查询唯一的一条结果,如果数据库中有多条符合条件的数据,它无法确定应该返回哪条数据。
解决办法
1:给queryWrapper增加查询条件
String username = employee.getUsername();
// 使用LambdaQueryWrapper构造查询条件
queryWrapper.eq(Employee::getUsername, username);
Employee emp = employeeService.getOne(queryWrapper);
2:使用ServiceImpl 类的 getOne时传入throwEx的参数,并设置为false;这样便可调用SqlHelper.getObject()返回集合中的第一个对象
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
Employee emp = employeeService.getOne(queryWrapper, true);
其他知识点
LambdaQueryWrapper的使用说明
是 MyBatis-Plus(简称 MP)中用于构建数据库查询条件的一个类
允许使用 Lambda 表达式的方式来构建查询条件
- 导入依赖:导入 MyBatis-Plus 的相关依赖,包括
mybatis-plus-core
和mybatis-plus-extension
。- 创建对象
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getDepartment, "IT") .ge(Employee::getSalary, 50000) .likeRight(Employee::getName, "John");
- 添加查询条件:使用
eq
、ne
、gt
、ge
、lt
、le
等方法来添加查询条件。每个方法的第一个参数是一个 Lambda 表达式,用于指定查询的字段,第二个参数是对应的值。/**queryWrapper.eq(Employee::getDepartment, "IT") .ge(Employee::getSalary, 50000) .likeRight(Employee::getName, "John");
MyBatis-Plus 中 LambdaQueryWrapper 类的一些常用查询方法
eq:等于(Equal)。
ne:不等于(Not Equal)。
gt:大于(Greater Than)。
ge:大于等于(Greater Than or Equal)。
lt:小于(Less Than)。
le:小于等于(Less Than or Equal)。
likeRight: 右模糊查询
*/添加排序条件
queryWrapper.orderByAsc(Employee::getJoiningDate);
最后可将queryWrapper给MyBatis-Plus的查询方法getOne(),getList()调用,如:
Employee emp = employeeService.getOne(queryWrapper);