JPA / Hibernate에서 flush ()의 올바른 사용 읽은 바에 따르면 지속성 컨텍스트의 내용이

flush () 메소드에 대한 정보를 수집하고 있었지만 언제 사용하고 올바르게 사용하는지 명확하지 않습니다. 내가 읽은 바에 따르면 지속성 컨텍스트의 내용이 데이터베이스와 동기화 될 것임을 이해했습니다. 즉, 미해결 문을 발행하거나 엔티티 데이터를 새로 고칩니다.

이제 두 개의 엔터티 AB(일대일 관계이지만 JPA에 의해 적용되거나 모델링되지 않은) 다음 시나리오가 있습니다. A수동으로 설정되고 자동 생성 된 IDENTITY 필드도있는 복합 PK가 있습니다 recordId. 이것은 recordId엔티티 B에 대한 외래 키로 작성되어야합니다 A. 저는 저축 A하고 B있으며 단일 거래입니다. 문제 A.recordId는를 호출 한 em.flush()후 명시 적으로 호출하지 않는 한 트랜잭션 내 에서 자동 생성 된 값을 사용할 수 없다는 것 em.persist()입니다 A. (자동 생성 된 IDENTITY PK가있는 경우 값이 엔티티에서 직접 업데이트되지만 여기서는 그렇지 않습니다.)

em.flush()거래 내에서 사용할 때 해를 끼칠 수 있습니까 ?



답변

아마도의 정확한 세부 사항 em.flush()은 구현에 따라 다릅니다. 어쨌든 일반적으로 Hibernate와 같은 JPA 공급자는 트랜잭션을 실제로 커밋 할 때까지 종종 데이터베이스로 보내야하는 SQL 명령을 캐시 할 수 있습니다. 예를 들어를 호출 em.persist()하면 Hibernate는 데이터베이스를 INSERT로 만들어야한다는 것을 기억하지만 트랜잭션을 커밋 할 때까지 실제로 명령을 실행하지 않습니다. Afaik, 이것은 주로 성능상의 이유로 수행됩니다.

어쨌든 어떤 경우에는 SQL 명령이 즉시 실행되기를 원합니다. 일반적으로 자동 생성 키 또는 데이터베이스 트리거와 같은 일부 부작용의 결과가 필요할 때.

어떤 em.flush()일은 내부 SQL 명령어 캐시를 비우, 데이터베이스에 즉시 실행하는 것입니다.

결론 : 해를 끼치 지 않습니다. SQL 명령을 데이터베이스에 보내는 최적의 타이밍과 관련하여 JPA 공급자 결정을 재정의하기 때문에 (사소한) 성능 저하가 발생할 수 있습니다.


답변

사실은, em.flush() 는 캐시 된 SQL 명령을 보내는 것 이상을 수행합니다. 지속성 컨텍스트를 기본 데이터베이스와 동기화하려고합니다. 캐시에 동기화 할 컬렉션이 포함 된 경우 프로세스에 많은 시간이 소요될 수 있습니다.

사용에 대한주의.


답변

em.flush ()는 트랜잭션 내에서 사용할 때 해를 끼칠 수 있습니까?

예, 필요 이상으로 오랫동안 데이터베이스에 잠금을 유지할 수 있습니다.

일반적으로 JPA를 사용할 때 트랜잭션 관리를 컨테이너 (일명 CMT-비즈니스 메소드에 @Transactional 어노테이션 사용)에 위임합니다. 즉, 메소드에 들어갈 때 트랜잭션이 자동으로 시작되고 마지막에 커밋 / 롤백됩니다. EntityManager가 데이터베이스 동기화를 처리하도록하면 SQL 문 실행은 커밋 직전에만 트리거되어 데이터베이스에서 잠깐 동안 잠금이 발생합니다. 그렇지 않으면 수동으로 플러시 된 쓰기 작업이 수동 플러시와 자동 커밋 사이에 잠금을 유지할 수 있으며 이는 남은 메서드 실행 시간에 따라 오래 걸릴 수 있습니다.

일부 작업은 자동으로 플러시를 트리거합니다. 동일한 세션에 대해 네이티브 쿼리 실행 (SQL 쿼리에서 도달하려면 EM 상태를 플러시해야 함), 네이티브 생성 ID를 사용하여 엔티티 삽입 (데이터베이스에서 생성되므로 insert 문은 따라서 EM은 생성 된 ID를 검색하고 관계를 적절히 관리 할 수 ​​있습니다.)


답변