JPA 병합 대 지속
지금까지 내 선호는 항상 EntityManager의 merge()
삽입 및 업데이트 처리를 사용하는 것입니다. 그러나 병합은 업데이트 / 삽입 전에 추가 선택 쿼리를 수행하여 레코드가 데이터베이스에 이미 존재하지 않도록합니다.
이제 데이터베이스에 대한 광범위한 (대량) 삽입이 필요한 프로젝트를 진행하고 있습니다. 성능 관점에서 볼 때 항상 지속될 개체의 새 인스턴스를 만들고 있다는 것을 절대적으로 알고있는 시나리오에서 병합 대신 지속을 사용하는 것이 합리적입니까?
충분할 merge
때 사용하는 것은 좋지 않습니다 . 훨씬 많은 작업을 수행합니다. 이 주제는 이전 에 StackOverflow 에서 논의되었으며 , 이 기사에서는 명확한 흐름 다이어그램과 함께 차이점을 자세히 설명합니다.persist
merge
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
'Program Tip' 카테고리의 다른 글
ASP.NET 5, .NET Core 및 ASP.NET Core 5의 차이점은 무엇입니까? (0) | 2020.11.15 |
---|---|
MySQL에 대한 최적의 varchar 크기는 무엇입니까? (0) | 2020.11.15 |
유효한 자바 스크립트 객체 속성 이름 (0) | 2020.11.15 |
드롭 다운 상자의 오버플로 텍스트에 대한 줄임표 (0) | 2020.11.15 |
자동으로 연결을 닫는 websocket (0) | 2020.11.15 |