2010-11-25 2 views
103

flush() 메소드에 대한 정보를 수집하고 있었지만 사용시기와 사용법이 명확하지 않습니다. 필자가 읽은 바에 따르면, 퍼시스턴스 컨텍스트의 내용이 데이터베이스와 동기화 될 것입니다. 이자형. 미해결 진술을 발표하거나 엔티티 데이터를 새로 고침합니다.JPA/Hibernate에서 flush()의 올바른 사용

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

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

답변

128

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

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

내부 SQL 명령어 캐시를 비우고 데이터베이스에 즉시 실행하려면 em.flush()을 수행하십시오.

결론 : 아무런 해를 끼치 지 않고 데이터베이스에 SQL 지침을 보내는 가장 좋은 타이밍과 관련하여 JPA 공급자 결정을 재정의하므로 성능이 저하 될 수 있습니다.

+1

그가 말한 내용. em.flush() 비헤이비어는 java.io.Flushable.flush()를 반향합니다. 버퍼 된 모든 데이터는 적절한 대상으로 보내집니다. – Erik

+4

flush()가 데이터베이스에 데이터를 보내는 경우? 그 이후에 예외가 발생하면 어떻게됩니까? 엔티티 관리자가 모든 것을 롤백합니까? 심지어 첫 번째 플러시에서 작성된 데이터? –

+88

flush()는 INSERT, UPDATE 등과 같이 SQL 명령어를 데이터베이스에 보냅니다. COMMIT를 보내지 않으므로 flush() 후에 예외가 발생해도 완전한 롤백이 가능합니다. – Flavio

0

사실 em.flush()은 단순히 캐시 된 SQL 명령을 보내는 것 이상의 기능을 수행합니다. 지속성 컨텍스트를 기본 데이터베이스와 동기화하려고 시도합니다. 캐시에 동기화 할 컬렉션이 포함되어 있으면 프로세스에서 많은 시간을 소비 할 수 있습니다.

사용시주의 사항.