REQUIRENEWの使用を避ける[Spring JPAコード生活白書]
8071 ワード
緒論
現在SpringJpaプロジェクトを行っていますが、問題を減らすために個人JPA会議を開きたいと思います.
REQUIRENEWの使用時に発生する可能性のある問題1
同じ識別子を持つオブジェクトは、異なる永続性コンテキストで変更される(
@Transactional
public String test(){
Member testMember1 = repository.findByMemberByMemberId(2L);
handler.innerTest();
testMember1.changeAge(35);
return null;
}
test()メソッドはコントローラから呼び出され、innerTestというメソッドが呼び出されます. @Transactional(propagation = Propagation.REQUIRES_NEW)
public void innerTest(){
Member testMember2 = memberRepository.findByMemberByMemberId(2L);
testMember2.changeName("Patrick");
}
現在のコード実行前のデータベースのデータは次のとおりです.![](https://s1.md5.ltd/image/9e8d3872221add8959426e52f706d2e8.png)
2番のメンバーの名前はテスト年齢33です
データベースにはマリア・ディビーが使用されています.独立性レベル2 REPEATABLE READ 適用されます.
結果を予測する
実際,2つの方法しかなければ,上記のコードに現れる問題をすぐに見つけることができるが,原理を知っていても
上図に示すように、コードが作成され、ターゲットが4分の5に入った場合は、どこで変更されたか、変更されていないかを一つ一つ探さなければなりません.
上記コード実行結果は、REQUIRENEWに適用される1つ以上のコードを反映しない.
原因を見てみましょう.
説明の便宜上、test()で開いているオブジェクトをT 1 innerTest()で開いているオブジェクトをT 2と呼ぶ
T 1で開くオブジェクト
![](https://s1.md5.ltd/image/6a3120262e3dc75b8a66668b9edb85e8.png)
![](https://s1.md5.ltd/image/43b6caa8bcfe9de91a7234edf28a44fe.png)
![](https://s1.md5.ltd/image/a1bad7d5d26d6d6ec8dc6354cb711078.png)
変更したオブジェクトをリフレッシュした後、SQL文をデバイスに送信してコミットします.
![](https://s1.md5.ltd/image/2a23cebc52c73360c622c1cd0dee3411.png)
![](https://s1.md5.ltd/image/e683de540b4c5cb6e8d3c4ec20f572d0.png)
REQUIRENEWオブジェクトコンテナの変更値はDeviに一度コミットされたが,最終T 1のコンテナオブジェクトに上書きされた.
![](https://s1.md5.ltd/image/c8cb16cdf22c22225ab2fe1bfb660eaf.png)
実はこのような状況に2つの方法があれば、本当に愚かな間違いを犯して、私がなぜこのようにするのかと思ったとき、コードが高度化して、対象が絡み合って、このようなことはいつでも起こり得る.
REQUIRENEWの使用時に発生する可能性のある問題2
1つ目の話題でご覧の通り、REQUIRENEWで使用しているメンバーオブジェクトに戻れば良いのではないでしょうか!
結論->この方法を使うな
今の状態はこうです.
![](https://s1.md5.ltd/image/ca344d5da0e96ed3c51b261d891596e3.png)
@Transactional
public String test(){
Member testMember1 = handler.innerTest();
testMember1.changeAge(35);
return null;
}
上記のようにtest()メソッドはinnerTest()メソッドを呼び出します. @Transactional(propagation = Propagation.REQUIRES_NEW)
public Member innerTest(){
Member testMember2 = memberRepository.findByMemberByMemberId(2L);
testMember2.changeName("Patrick");
return testMember2;
}
上記のコードの終了時に結果値を予測できます.1.REQUITES NEWが実行され、testで名前がPatrick、年齢が35に変更されました.
[原句]何なのか分かりませんが、間違えました.
3.年齢は35歳になる.
4.名前だけが変わる.
正解は4番
これは、test()T 1オブジェクトが開始されると、T 1コンテナが第2のメンバーを永続コンテキストに格納しないためです.
TT 1コンテナには、永続的なコンテキスト内の2番目のメンバーはありません.T 2の2番目のメンバーを保存し、デバイスにリフレッシュし、メンバーをT 1オブジェクトコンテナに戻すことで、T 1持続性コンテキストに入ることができます.大学ではありません.
(もちろん、このようなエラーはその前に障害をもたらします)testMember 1->非永続オブジェクトは他の開発者に楽しく遊ばれます.しかし、テレビでも何も起こらない.
改善方法
変更を検出してデータベースにアクセスするには、最初にロードする場所、変更を変更する場所が非常に困難になります.
n/a.結論
ネットワーク名を使用する場合は、同じIDが異なる永続コンテナで異なるアドレス値に変更されることを避ける必要があります.
Reference
この問題について(REQUIRENEWの使用を避ける[Spring JPAコード生活白書]), 我々は、より多くの情報をここで見つけました https://velog.io/@dkajffkem/REQUIRESNEW-를-사용하는-상황을-피하자Spring-JPA-코드-생활백서テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol