[TIL]JPA本体演算を使用する際の注意点.

5015 ワード


一括演算とは?


エンティティを最初に変更するには、トランザクションでエンティティを変更します.
永続性コンテキストに変更を検出させます.
// 트랜잭션 시작

// 수정 작업
member.setName("바뀐 이름");

// 커밋 -> 커밋 시에 영속성 컨텍스트가 변경감지를 시행하고 수정 쿼리를 DB에 날린다.
削除の場合は、EntityManagerのremove()メソッドをトランザクションで呼び出すこともできます.
しかし,この方法で数百以上のシンボルを処理するには長い時間がかかる.
このとき,複数のイベントを一度に処理するバッチ演算を用いることができる.

String queryString = 
	"update Member m from set m.name = '아저씨' where m.age > :age";
    
int resultCount = em.createQuery(queryString)
			.setParameter("age", 40)
            		.executeUpdate(); // 벌크 연산 사용.
上の例では40歳以上の旧友たちの名前をおじさんに変えています.

本体演算の注意点


バッチ演算を使用する場合は、永続性コンテキストを無視してデータベースを直接クエリーします.
この場合、データベース内の変更は永続性コンテキストに反映されません.
データの整合性が損なわれる可能性があります.
// 이 엔티티의 age 는 45이다.
Member member = em.createQuery("select m from MEmber m where m.name =:name", Member.class)
				.setParameter("name", "아저씨10")
               			.getSingleResult();

// 영속성 컨텍스트를 거치지 않고 바로 DB로 쿼리를 날린다.
em.createQuery("select Member m set m.age = 12")
	.executeUpdate();
    
// 나이가 바뀌지 않았다...
System.out.println("member.getAge() = " + member.getAge()); // 45 
上の悲しいサンプルコードの手順を見てみましょう.
検索
  • nameはおじさん10のメンバーです.クエリは成功しました.このエンティティは現在永続的なコンテキストにあります.
  • すべてのメンバーの年齢を12に変更するバッチ演算を行います.永続性コンテキストなしで、DBに直接クエリーします.そのため、DBのみを変更しました.
  • エンティティの年齢を問い合せます.永続性コンテキストに変化はないので、45は直接出力される.
  • 解決策


  • em.refresh()の使用
    上記の問題を解決するには、一括演算の後にem.refresh(member)を使用しておじさん10に再度問い合わせるだけでよい.

  • まず一括演算を実行
    簡単です.Updateの一括演算を先に実行して問い合わせることができます.

  • マスター演算の実行後に永続コンテキストを初期化
    マスター演算を実行すると、永続性コンテキストの残りのエンティティが削除されます.
    永続性コンテキストにエンティティが存在しないため、クエリー・クエリーはデータベースに飛ぶことになります.