Hibernate에서 session.flush ()의 용도는 무엇입니까?


110

레코드를 업데이트 할 때 session.flush()Hibernate와 함께 사용할 수 있습니다 . 무엇이 필요 flush()합니까?

답변:


138

세션을 플러시하면 Hibernate가의 메모리 내 상태를 Session데이터베이스와 동기화 합니다 (즉, 변경 사항을 데이터베이스에 기록). 기본적으로 Hibernate는 자동으로 변경 사항을 플러시합니다.

  • 일부 쿼리 실행 전
  • 트랜잭션이 커밋 될 때

명시 적으로 플러시를 허용하면 Session일부 상황 (ID 할당, 세션 크기 제어 등)에서 필요할 수있는 더 세밀한 제어가 제공됩니다.


8
이 답변은 DEFAULT Hibernate 동작을 설명합니다. 플러시 동작은 플러시 모드 설정을 통해 변경할 수 있습니다. 자세한 내용은 docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/… (버전 3.5)에 있습니다.
SteveT

1
나는 당신이 말하는 것을 정확히 말한 문서를 찾았 지만 우선 순위가 무엇인지에 대한 질문이 있습니다 1) 코드를 사용하여 객체를 저장 id = session.save(obj);하고 트랜잭션이 바로 다음 줄에서 커밋되었지만 obj가 저장되지 않는 클래스가 DB에, 왜? 2) session.save(obj);커밋과 함께 사용하여 obj를 저장 하고 반환하는 동안 사용했습니다 return obj.getprimaryID();.이 경우 obj는 DB에 저장됩니다. 그렇다면 왜 이런 행동이 일어나고 있습니까?
Amogh

74

위의 답변에서 올바르게 말했듯이 호출 flush()하면 데이터베이스에서 SQL 명령을 실행하도록 최대 절전 모드를 강제 실행합니다. 그러나 변경 사항은 아직 "커밋"되지 않았 음을 이해하십시오. 따라서 플러시를 수행 한 후 커밋을 수행하기 전에 DB에 직접 액세스하고 (예 : SQL 프롬프트에서) 수정 된 행을 확인하면 변경 사항이 표시되지 않습니다.

이것은 2 개의 SQL 명령 세션을 여는 것과 같습니다. 그리고 한 세션에서 수행 된 변경 사항은 커밋 될 때까지 다른 사용자에게 표시되지 않습니다.


12
음-변화가 약간 보일 수 있습니다. 예를 들어, 커밋되지 않은 행은 삽입되었지만 커밋되지 않은 행에 잠금을 생성하고 트랜잭션이 커밋되거나 롤백 될 때까지 다른 세션에서 동일한 행을 삽입하는 것을 지연시킬 수 있습니다. 그래서 그것은 완전히 보이지 않습니다.
rghome

2
나는 웹을 통해 서핑했고 이것이 마침내 나를 얻도록 만든 대답입니다. 감사.
싯다르타

for 루프에 .flush ()를 넣는 사용은 무엇입니까? 커밋 ()이 끝에서 플러시를 수행하면?
Eildosa

@Kaushik Lele 플러시 후 데이터가 보이지 않으면 flush ()의 요점은 무엇입니까? 이것이 도움이되는 더 세밀한 사용 사례에 대해 자세히 설명해 주시겠습니까?
java_geek

28

나는 우리가 호출 할 때 우리 session.flush()의 명령문이 데이터베이스에서 실행되지만 커밋되지 않는다는 것을 알고 있습니다.

flush()세션 객체에서 메서드를 호출하지 않고 commit 메서드를 호출하면 내부적으로 데이터베이스에서 명령문을 실행 한 다음 커밋하는 작업을 수행 한다고 가정 합니다.

commit=flush+commit (기능의 경우)

따라서 Session 객체에 대해 flush () 메서드를 호출하면 커밋되지 않고 데이터베이스에 도달하고 쿼리를 실행하고 롤백도 수행된다는 결론을 내립니다.

커밋하기 위해 Transaction 객체에 commit ()을 사용합니다.


플러시의 필요성에 대해 자세히 설명해 주시겠습니까?
java_geek

14

세션을 플러시하면 현재 세션에있는 데이터가 데이터베이스에있는 것과 동기화됩니다.

Hibernate 웹 사이트에 대한 추가 정보 :

flush()세션이 JDBC 호출을 실행하는시기에 대한 보장이 전혀없고 실행되는 순서 만 보장 할 수 없기 때문에 유용합니다 flush().


사용자가 시퀀스에 대해 걱정해야하는 시나리오를 제공 할 수 있습니까? Hibernate를 사용하는 것은 DB 관련 사항을 사용자에게 투명하게 만드는 것입니다. "커밋"하면 자동으로 플러시가 발생합니다. 플러시를하지만 커밋하지 않는 시나리오는 무엇입니까?
Kaushik Lele

1
@KaushikLele이 질문을 참조 할 수 있습니다. stackoverflow.com/questions/37382872/…
GMsoF

10

flush트랜잭션이 커밋 될 때가 아니라 알려진 위치에서 유효성 검사 제약 조건이 실현되고 감지되도록 강제 하는 데 사용할 수 있습니다 . commit선언적 논리, 컨테이너 또는 템플릿을 통해 일부 프레임 워크 논리에 의해 암시 적으로 호출 될 수 있습니다 . 이 경우 throw되는 예외는 포착 및 처리하기 어려울 수 있습니다 (코드에서 너무 높을 수 있음).

예를 들어 save()주소에 고유 한 제약 조건이있는 새 EmailAddress 객체 인 경우 커밋 할 때까지 오류가 발생하지 않습니다.

호출 flush()하면 행이 강제로 삽입되고 중복이있는 경우 예외가 발생합니다.

그러나 예외 후에 세션을 롤백해야합니다.


4

위의 모든 답변을 클럽 화하고 Flush () 메서드를 Session.save ()와 연결하여 더 중요하게 만들고 싶습니다.

Hibernate save ()는 엔티티를 데이터베이스에 저장하는 데 사용할 수 있습니다. 트랜잭션 외부에서이 메서드를 호출 할 수 있으므로이 메서드가 데이터를 저장하는 것을 좋아하지 않습니다. 트랜잭션없이 이것을 사용하고 엔터티간에 캐스 케이 딩이있는 경우 세션을 플러시하지 않는 한 기본 엔터티 만 저장됩니다.

flush () : 세션을 강제로 플러시합니다. 세션 데이터를 데이터베이스와 동기화하는 데 사용됩니다.

session.flush ()를 호출하면 명령문이 데이터베이스에서 실행되지만 커밋되지는 않습니다. session.flush ()를 호출하지 않고 session.commit ()을 호출하면 내부적으로 commit () 메서드가 문을 실행하고 커밋합니다.

그래서 commit () = flush + commit. 따라서 session.flush ()는 데이터베이스에서 명령문을 실행하고 (커밋은 아님) 명령문은 더 이상 메모리에 없습니다. 세션을 강제로 플러시합니다.

몇 가지 중요한 사항 :

트랜잭션 경계 외부에 저장하는 것을 피해야합니다. 그렇지 않으면 매핑 된 엔티티가 저장되지 않아 데이터 불일치가 발생합니다. 예외 나 경고가 발생하지 않기 때문에 세션 플러시를 잊어 버리는 것은 매우 정상입니다. 기본적으로 Hibernate는 자동으로 변경 사항을 플러시합니다 : 트랜잭션이 커밋 될 때 일부 쿼리 실행 전에 Session을 명시 적으로 플러시하도록 허용하면 일부 상황에서 필요할 수있는 더 미세한 제어를 제공합니다 (ID 할당, 세션 크기 제어). )


3

flush() 메서드는 Hibernate가 세션을 플러시하도록합니다. setFlushMode()메서드 를 사용하여 세션에 대해 플러시 모드를 사용하도록 Hibernate를 구성 할 수 있습니다 . 현재 세션의 플러시 모드를 얻으려면 getFlushMode()메서드 를 사용할 수 있습니다 . 세션이 더티 여부를 확인하려면 isDirty()방법 을 사용할 수 있습니다 . 기본적으로 Hibernate는 세션 비우기를 관리합니다.

문서에 명시된대로 :

https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/flushing/Flushing.html

홍조

플러싱은 지속성 컨텍스트의 상태를 기본 데이터베이스와 동기화하는 프로세스입니다. EntityManager및 하이버 네이트 Session애플리케이션 개발자 엔티티의 지속 상태를 변경할 수있는 방법들의 세트를 노출시킨다.

지속성 컨텍스트는 모든 엔터티 상태 변경을 큐에 넣는 트랜잭션 쓰기 숨김 캐시 역할을합니다. 모든 write-behind 캐시와 마찬가지로 변경 사항은 먼저 메모리에 적용되고 플러시 시간 동안 데이터베이스와 동기화됩니다. 플러시 작업은 모든 엔티티 상태 변경을 가져 와서 INSERT, UPDATE또는 DELETE문으로 변환합니다 .

플러싱 전략은 현재 실행중인 Hibernate 세션 의 flushMode 에 의해 제공됩니다 . JPA는 두 가지 플러시 전략 ( AUTOCOMMIT) 만 정의하지만 Hibernate는 훨씬 더 광범위한 플러시 유형 스펙트럼을 가지고 있습니다.

  • ALWAYS: 모든 쿼리 전에 세션을 플러시합니다.
  • AUTO: 이것은 기본 모드이며 필요한 경우에만 세션을 플러시합니다.
  • COMMIT: 세션은 너무 일찍 플러시 될 수 있지만 현재 트랜잭션이 커밋 될 때까지 플러시를 지연하려고합니다.
  • MANUAL: 세션 플러싱은 Session.flush()지속성 컨텍스트 변경 사항을 적용하기 위해 명시 적으로 호출해야하는 응용 프로그램에 위임 됩니다.

기본적으로 Hibernate는 AUTO다음 상황에서 플러시를 트리거하는 플러시 모드를 사용합니다 .

  • 거래를 수행하기 전에
  • 대기중인 엔티티 작업과 겹치는 JPQL / HQL 쿼리를 실행하기 전에
  • 등록 된 동기화가없는 네이티브 SQL 쿼리를 실행하기 전에

1

호출 EntityManager#flush에는 부작용이 있습니다 . 생성 된 ID 값 (시퀀스 값)이있는 엔티티 유형에 편리하게 사용됩니다. 이러한 ID는 기본 지속성 레이어와 동기화 할 때만 사용할 수 있습니다. 현재 트랜잭션이 종료되기 전에이 ID가 필요한 경우 (예 : 로깅 목적으로) 세션 플러시가 필요합니다.


0

이 방법을 사용하면 플러시 프로세스가 나타납니다. 이 프로세스는 상태 변경을 감지하고 각 SQL 문을 실행하여 데이터베이스의 상태를 세션의 상태와 동기화합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.