[JPA]汚れ検査


@Transactional
    public Long update(Long id, PostsUpdateRequestDto requestDto) {
        Posts posts = postsRepository.findById(id)
                                    .orElseThrow(() -> new IllegalArgumentException("해당 게시글이 없습니다. id = " + id));

        posts.update(requestDto.getTitle(), requestDto.getContent());

        return id;
    }
上記のコードでは、データベースに更新クエリーを発行することなく、エンティティ・オブジェクトの値のみが変更されます.
この点が可能なのは、「汚れ検査」(Dirty Checking)のおかげだ.

汚れ検査


ダーティ・フィルタは、エンティティへの変更をデータベースに自動的に反映します.
エンティティが永続性コンテキストに保存されると、JPAはスナップショットの初期クエリーステータスを保持します.
次に、フラッシュポイントでスナップショットと比較して変更されたエンティティを検索し、変更をデータベースに渡します.
public Long update(Long id, PostsUpdaterequestDto requestDto) {
        EntityManager em = em.createEntityManager();	//엔티티 매니저 생성
        EntityTransaction transaction = em.getTransaction();	//트랜잭션 시작

        transaction.begin();	//트랜잭션 시작

        Posts posts = em.find(Posts.class, id);
        posts.update(requestDto.getTitle(), requestDto.getContent());	//영속 엔티티 데이터 수정

        transaction.commit();	//트랜잭션 커밋
        
        return id;
    }
上記のサンプルコードは、ネイティブコードに変更されました.
汚れたスイッチの動作原理は次のとおりです.
  • トランザクションがコミットされるとflush()が呼び出されます.
  • 永続コンテキスト内のすべてのエンティティをスナップショットと比較します.
  • エンティティ
  • が変更された場合、UPDATE SQLが作成され、書き込み遅延SQLリポジトリに保存されます.
  • 書き込み遅延SQLをデータベースに送信します.
  • データベース・トランザクションをコミットします.
  • トランザクションでは、エンティティを変更する必要があり、永続性コンテキストによって管理される「永続状態」(Managed)のエンティティにのみ適用されます.

    したがって、データベースに保存されていないエンティティオブジェクト(ゼロ以外のプロパティ)または分離、消去、閉じられたエンティティ(準ゼロプロパティ)は、値の変更時にデータベースに反映されません.
    汚いフィルタによって生成されたUPDATE SQLは、エンティティ内のすべてのフィールドを更新します.
    すべてのフィールドをDBに送信すると、データ転送量が増加しますが、変更クエリーは常に同じであるため、これらのフィールドを事前に作成して再使用できます.また、同じクエリーをデータベースの観点から受信すると、以前にグループ化されたクエリーを再利用できます.
    必要なフィールドのみを更新する場合は、エンティティの定義時に@DynamicUpdate宣言を追加できます.