Program Tip

JPA 병합 대 지속

programtip 2020. 11. 15. 11:39
반응형

JPA 병합 대 지속


지금까지 내 선호는 항상 EntityManager의 merge()삽입 및 업데이트 처리를 사용하는 것입니다. 그러나 병합은 업데이트 / 삽입 전에 추가 선택 쿼리를 수행하여 레코드가 데이터베이스에 이미 존재하지 않도록합니다.

이제 데이터베이스에 대한 광범위한 (대량) 삽입이 필요한 프로젝트를 진행하고 있습니다. 성능 관점에서 볼 때 항상 지속될 개체의 새 인스턴스를 만들고 있다는 것을 절대적으로 알고있는 시나리오에서 병합 대신 지속을 사용하는 것이 합리적입니까?


충분할 merge사용하는 것은 좋지 않습니다 . 훨씬 많은 작업을 수행합니다. 이 주제는 이전 에 StackOverflow 에서 논의되었으며 , 이 기사에서는 명확한 흐름 다이어그램과 함께 차이점을 자세히 설명합니다.persistmerge


persist()당신이 말했듯이 나는 확실히 지속 할 것입니다 .

(...) 나는 항상 지속될 객체의 새로운 인스턴스를 만들고 있다는 것을 절대적으로 알고 있습니다. (...)

이것이 바로이 방법의 전부입니다. 엔티티가 이미 존재하는 경우에 당신을 보호 할 것입니다 (그리고 당신의 트랜잭션을 롤백 할 것입니다).


할당 된 생성기를 사용하는 경우 merge대신 사용 persist하면 중복 SQL 문이 발생하여 성능에 영향을 미칠 수 있습니다.

또한 관리되는 엔티티에 대해 병합을 호출하는 것도 실수입니다. 관리되는 엔티티는 Hibernate에 의해 자동으로 관리되고 Persistence Context 플러시더티 검사 메커니즘의해 해당 상태가 데이터베이스 레코드와 동기화되기 때문 입니다.

이 모든 것이 어떻게 작동하는지 이해하려면 먼저 Hibernate가 개발자의 사고 방식을 SQL 문에서 엔티티 상태 전환으로 전환 한다는 것을 알아야합니다 .

엔티티가 Hibernate에 의해 능동적으로 관리되면 모든 변경 사항이 데이터베이스에 자동으로 전파됩니다.

Hibernate는 현재 연결된 엔티티를 모니터링합니다. 그러나 엔터티가 관리 되려면 올바른 엔터티 상태에 있어야합니다.

먼저 모든 엔티티 상태를 정의해야합니다.

  • 신규 (임시)

    Hibernate Session(일명 Persistence Context)와 연관 되지 않았고 어떤 데이터베이스 테이블 행에도 매핑 되지 않은 새로 생성 된 객체 는 New (Transient) 상태로 간주됩니다.

    지속되기 위해서는 EntityManager#persist메서드 를 명시 적으로 호출 하거나 전 이적 지속성 메커니즘을 사용해야합니다.

  • 영구 (관리)

    영구 엔터티는 데이터베이스 테이블 행과 연결되어 있으며 현재 실행중인 Persistence Context에 의해 관리되고 있습니다. 이러한 엔터티에 대한 모든 변경 사항이 감지되어 데이터베이스에 전파됩니다 (세션 플러시 시간 동안). Hibernate를 사용하면 더 이상 INSERT / UPDATE / DELETE 문을 실행할 필요가 없습니다. Hibernate는 트랜잭션의 write-behind 작업 스타일을 사용하며 변경 사항은 현재 Session플러시 시간 동안 가장 마지막 책임있는 순간에 동기화됩니다 .

  • 분리됨

    현재 실행중인 지속성 컨텍스트가 닫히면 이전에 관리 된 모든 엔티티가 분리됩니다. 연속적인 변경 사항은 더 이상 추적되지 않으며 자동 데이터베이스 동기화가 발생하지 않습니다.

    분리 된 엔티티를 활성 Hibernate 세션에 연결하려면 다음 옵션 중 하나를 선택할 수 있습니다.

    • 다시 연결

      Hibernate (JPA 2.1 아님)는 Session # update 메소드를 통한 재 연결을 지원합니다. Hibernate Session은 주어진 데이터베이스 행에 대해 하나의 Entity 객체 만 연관시킬 수 있습니다. 이는 지속성 컨텍스트가 메모리 내 캐시 (첫 번째 수준 캐시)로 작동하고 하나의 값 (엔티티) 만 주어진 키 (엔티티 유형 및 데이터베이스 식별자)와 연결되기 때문입니다. 엔티티는 현재 Hibernate 세션에 이미 연관된 다른 JVM 객체 (동일한 데이터베이스 행과 일치)가없는 경우에만 재 부착 될 수 있습니다.

    • 병합

    병합은 분리 된 엔티티 상태 (소스)를 관리 엔티티 인스턴스 (대상)에 복사합니다. 병합 엔터티가 현재 세션에 해당하는 항목이 없으면 데이터베이스에서 하나를 가져옵니다. 분리 된 개체 인스턴스는 병합 작업 후에도 계속 분리 된 상태로 유지됩니다.

  • 제거됨

    JPA는 관리되는 엔터티 만 제거 할 수 있도록 요구하지만 Hibernate는 분리 된 엔터티를 삭제할 수도 있습니다 (Session # delete 메서드 호출을 통해서만 가능). 제거 된 엔터티는 삭제 만 예약되며 실제 데이터베이스 DELETE 문은 세션 플러시 시간 동안 실행됩니다.

JPA 상태 전환을 더 잘 이해하기 위해 다음 다이어그램을 시각화 할 수 있습니다.

여기에 이미지 설명 입력

또는 Hibernate 특정 API를 사용하는 경우 :

여기에 이미지 설명 입력

참고 URL : https://stackoverflow.com/questions/8469871/jpa-merge-vs-persist

반응형