記事ディレクトリ
1. エラーを再現します
今日、テスト女性は、テスト環境のバックグラウンド管理システムのホームページでエラーが報告されたと言い、次の写真を送ってきました。
テスト環境のデータベースは変更できないため、テスト環境のデータベースはバックアップしてローカルにコピーすることしかできません。
次の図に示すように、バックアップ上にマウスを置き、右クリックして「バックアップの復元」を選択し、「開始」をクリックします。
[注意事項] バックアップを復元すると、現在のデータベース内の既存のデータが置き換えられるため、慎重に行う必要があります。
次の図に示すように、ローカルにバックアップした後、ローカルを使用してKnife4j
問題のあるインターフェイスをテストします。
案の定、例外が発生しました 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. 分析エラー
次の図に示すように、これChatGPT
を使用して質問に戻ることができます。
しかし、ChatGP
私の質問に答えることはできません。この例外を自分で分析することしかできません。
私たちはExpected one result (or null) to be returned by selectOne(), but found: 2
この文を分析して中国語に翻訳することに重点を置いています。希望返回1个结果(或者null),但返回了2个结果。
2 つの結果が返されるのはなぜですか? 分析を続けます。
selectOne()
次のコードに示すように、メソッドが呼び出される場所を見つけます。
......
// 获取企业用户 id
Wrapper<EnterpriseUser> queryWrapper =new LambdaQueryWrapper<EnterpriseUser>()
.eq(EnterpriseUser::getUserId, tokenProperties.getUserId());
EnterpriseUser enterpriseUser = enterpriseUserService.selectOne(queryWrapper);
......
同時に、コードに示すように、mybatis
出力されたステートメントを見つけます。SQL
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
上記のSQL
ステートメントから判断すると、データの一部が返されるのは事実です2
。
ただしselectOne()
、このメソッドはデータの一部しか返せないため、現在はデータの一部を1
返すため、上記のエラーが報告されます。2
同時に、クエリ条件に従って複数のデータがクエリされた場合、getOne()
メソッドは上記のエラーも報告します。
したがって、selectOne()
orgetOne()
メソッドを使用して複数のデータをクエリすることはできません。
3. 問題を解決する
プロダクトマネージャーとコミュニケーションをとり、プロダクトマネージャーから提示された企画書の中から最新のデータを選択します。
最新のデータを選択するには、次の 2 つの方法を使用します。
list()
次のコードに示すように、メソッドをselectOne()
メソッドに置き換えます。
......
// 获取企业用户 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);
}
......
selectOne()
次のコードに示すように、メソッドの代わりにメソッドを書き換えます。
EnterpriseUserMapper
クラスの新しいselectOneByLimit
メソッド
/**
* 通过用户查询企业用户
*
* @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);
EnterpriseUserService
クラスselectOneByLimit
の新しいメソッド
/**
* 通过用户查询企业用户
*
* @author super先生
* @datetime 2023/3/2:13:38
* @param userId 用户id
* @return 返回企业用户信息
*/
public EnterpriseUser selectOneByLimit(Long userId) {
return enterpriseUserMapper.selectOneByLimit(userId);
}
- その他のサービスクラス呼び出し
EnterpriseUserService#selectOneByLimit
メソッド
......
EnterpriseUser enterpriseUser = enterpriseUserService.selectOneByLimit(tokenProperties.getUserId());
......
4. 記事の備考
上記のエラー メッセージが報告されます: Expected one result (or null) to be returned by selectOne(), but found: 2
。
通常、データの一部をクエリする必要があるため、selectOne()
orgetOne()
メソッドを使用します。ただし、クエリ条件に従って、複数のデータがクエリされます。
変更方法は、プロダクトマネージャーを自分で選択できます。プロダクトマネージャーのニーズに応じて、最適なソリューションを決定します。
私の解決策で問題を解決できない場合は、コメント欄にメッセージを残していただければ、みんなで一緒に進歩していきます。