Multiple ways to solve Expected one result (or null) to be returned by selectOne(), but found: x error

1. Reproduce the error


Today, the test lady told me that the home page of the background management system of the test environment reported an error, and sent the following picture:

insert image description here

Since the database of the test environment cannot be modified, the database of the test environment can only be backed up and then copied to my local.

Place the mouse on the backup, right-click to select Restore Backup, and click Start, as shown in the figure below:

insert image description here

[Precautions] Restoring the backup will replace the existing data in the current database, so this should be done with caution.

After backing up to my local, use the local Knife4jto test the problematic interface, as shown in the following figure:

insert image description here

Sure enough, an exception occurred, ie org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2.

2. Analysis errors


It is catching up ChatGPTwith the fire, and I can use it to return to my question, as shown in the following figure:

insert image description here

But ChatGPcan't answer my question, I can only analyze this exception by myself.

We focus on analyzing Expected one result (or null) to be returned by selectOne(), but found: 2this sentence and translating it into Chinese is希望返回1个结果(或者null),但返回了2个结果。

Why are two results returned? We continue to analyze.

Locate selectOne()the place where the method is called, as shown in the following code:

......
 // 获取企业用户 id
Wrapper<EnterpriseUser> queryWrapper =new LambdaQueryWrapper<EnterpriseUser>()
   .eq(EnterpriseUser::getUserId, tokenProperties.getUserId());

EnterpriseUser enterpriseUser = enterpriseUserService.selectOne(queryWrapper);
......

At the same time, find out mybatisthe printed SQLstatement, as shown in the code:

SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2165c177] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@6c5e6da] will not be managed by Spring

==>  Preparing: select * from enterprise_user_role r where r.enterprise_user_id = ? and r.role_id in(select id from role where deleted = 0)
==> Parameters: 1(Long)
<==    Columns: id, enterprise_user_id, role_id, create_time, update_time, deleted
<==        Row: 37, 1, 4, 2023-01-03 16:26:29, 2023-01-03 16:26:28, 0
<==        Row: 94, 1, 17, 2023-03-02 10:00:39, 2023-03-02 10:00:37, 0
<==      Total: 2

Judging from the above SQLstatement, it is true that a piece of data is returned 2.

But selectOne()the method can only return 1pieces of data, and now it returns 2pieces of data, so the above error is reported.

At the same time, if multiple pieces of data are queried according to the query conditions, getOne()the method will also report the above error.

Therefore, we cannot use selectOne()the or getOne()method to query multiple pieces of data.

3. Solve the problem


After communicating with the product manager, choose the latest piece of data from the plan given by the product manager.

I use the following two methods to select the latest piece of data.

  1. Replace list()the method with selectOne()a method, as shown in the following code:
......
 // 获取企业用户 id
Wrapper<EnterpriseUser> queryWrapper = new LambdaQueryWrapper<EnterpriseUser>()
     .eq(EnterpriseUser::getUserId, tokenProperties.getUserId())
     .orderByDesc(EnterpriseUser::getCreateTime);

 EnterpriseUser enterpriseUser = null;
 List<EnterpriseUser> enterpriseUsers = enterpriseUserService.list(queryWrapper);
 if (!enterpriseUsers.isEmpty()) {
    
    
   enterpriseUser = enterpriseUsers.get(0);
 }
......
  1. Instead of selectOne()a method, rewrite a method, as shown in the following code:
  • EnterpriseUserMapperselectOneByLimitnew method in class
/**
 * 通过用户查询企业用户
 *
 * @author super先生
 * @datetime 2023/3/2:13:34
 * @param userId 用户id
 * @return 返回企业用户信息
 */
@Select(
    "SELECT "
        + " *  "
        + "FROM "
        + " enterprise_user_role r  "
        + "WHERE "
        + " r.enterprise_user_id = #{userId}  "
        + " AND r.role_id IN ( SELECT id FROM role WHERE deleted = 0 ) "
        + "ORDER BY create_time DESC "
        + "LIMIT 1")
EnterpriseUser selectOneByLimit(@Param("userId") Long userId);
  • EnterpriseUserServiceselectOneByLimitnew method of class
/**
 * 通过用户查询企业用户
 *
 * @author super先生
 * @datetime 2023/3/2:13:38
 * @param userId 用户id
 * @return 返回企业用户信息
 */
public EnterpriseUser selectOneByLimit(Long userId) {
    
    
  return enterpriseUserMapper.selectOneByLimit(userId);
}
  • Other service class call EnterpriseUserService#selectOneByLimitmethods
......
EnterpriseUser enterpriseUser = enterpriseUserService.selectOneByLimit(tokenProperties.getUserId());
......

4. Article Remarks


The above error message is reported: Expected one result (or null) to be returned by selectOne(), but found: 2.

Generally, you want to query a piece of data, so you use selectOne()the or getOne()method. But according to your query conditions, multiple pieces of data are queried.

How to modify it, you can choose the product manager yourself. According to the needs of product managers, to determine the best solution.

If my solution cannot solve your problem, you can leave a message in the comment area, and everyone will make progress together.

Guess you like

Origin blog.csdn.net/lvoelife/article/details/129299453