이 기사의 주요 연구는 Hibernate의 session_flush 및 격리 수준입니다. 특정 소개 및 예제는 다음과 같습니다.
먼저 몇 가지 개념을 살펴 보겠습니다.
1. Dirty Reading : Dirty Reading을 잘못된 데이터의 읽기라고도합니다. 이는 데이터베이스 액세스 중에 T1이 특정 값을 수정 한 다음 T2가 값을 읽는 것을 의미합니다. 그 후, T1은 어떤 이유로 값의 수정을 취소하여 T2에 의해 읽는 데이터가 유효하지 않습니다. Dirty Reading은 사물이 데이터에 액세스하고 데이터를 수정하는 경우이 수정이 데이터베이스에 제출되지 않았을 때 다른 것이이 데이터에 액세스 한 다음이 데이터를 사용한다는 것을 의미합니다. 이 데이터는 여전히 제출되지 않기 때문에 다른 것들에 의해 읽은 데이터는 더러운 데이터이며 더러운 데이터를 기반으로 수행 된 작업은 잘못되었습니다.
2. 반복되지 않음 읽기 : 예를 들어, 게시물을 읽을 때 내가 찾은 데이터는 Zhang San과 Li Si였습니다. 그런 다음 새로 고침 후 초기 Zhang San이 Zhang Ba가 된 것을 알았습니다. 내가 읽은 데이터가 반복되지 않았기 때문에 소위 반복 할 수없는 판독 값입니다.
3. 판타지 독서 : 데이터를 찾을 때 3 개의 레코드를 찾기 시작했습니다. 그것을 새로 고침했을 때, 나는 레코드가 8이된다는 것을 알았습니다. 이것은 판타지 독서입니다.
4. 읽기 제출 : 제출 후에 만 읽을 수 있습니다. 오라클은 이것에 대한 기본값을 기본적으로 만듭니다. 이런 식으로 더러운 독서는 없습니다.
5. 반복성 : 반복 할 수없는 독서의 반대입니다. 반복 할 수없는 독서를 피할 수는 있지만 팬텀 독서를 피할 수는 없습니다.
6. 직렬화 : 이 방법은 매우 엄격합니다. 평신도의 용어로는 내가 무언가를 할 때 아무도 할 수 없습니다. 매우 안전하지만 매우 비효율적입니다.
아래에서는 최대 절전 모드 캐시 클리어런스의 적용을 이해하기 위해 실제 예제를 사용합니다.
최대 절전 모드 매핑 데이터베이스는 기본 키 생성 전략과 관련이 있습니다.
UUID에서 기본 키를 생성하는 예 :
공개 클래스 사용자 {private string uid; private string uname; private date birthday; public string getUid () {return uid;} public void setUid (string uid) {this.uid = uid;} public string getUname () {return uname;} public void setuname (string uname) {this.uname;} 공개 날짜 getbirthday () getbirthday () setbirthday (날짜 생일) {this.birthday = 생일;}}user.hbm.xml :
<? xml 버전 = "1.0"?> <! docType Hibernate Mapping Public "-// hibernate/hibernate 매핑 dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">-패키지 이름을 대표합니다. package = "com.lixue.bean"> <!-클래스 노드의 이름은 엔티티의 클래스 이름을 나타내며 테이블은 데이터베이스의 테이블에 맵핑 된 엔티티의 이름을 나타냅니다.> <class name = "user"table = "t_user"> <id name = "uid"> <!-uuid-> <property name = "uneame"/<generator를 통해 생성됩니다. 이름 = "생일"/> </class> </hibernate-mapping>
테스트 방법 :
/ ***UUID 1 차 키 생성 전략을 테스트하십시오*/ public void testsave1 () {/*정의 된 세션 및 사물*/ 세션 세션 = null; 거래 거래 = null; { /*세션을 얻으십시오* / 세션 = hibernateutils.getSession (); 트랜잭션 = session.beginTransaction (); /*사용자 만들기*/ 사용자 user = 새 사용자 (); user.setuname ( "xi jinping"); user.setbirthday (새 날짜 ()); / *** 사용자의 기본 키 생성 전략은 UUID이므로 저장 후에는 SAVE MANAGANION의 사용자 만 포함합니다.* 삽입 문은 발행되지 않지만 ID가 생성되지 않았으며, insistenceSindateBase 상태는 false*/ session.save (사용자)입니다. /** * Calling Flush, Hibernate는 캐시를 정리합니다 (세션-> 세션에 임시 컬렉션에 삽입물에 삽입물을 삽입하여 데이터베이스에 삽입하고 임시 컬렉션을 지우십시오) * 현재 데이터베이스에서 데이터를 볼 수 없지만 데이터베이스의 격리 수준이 읽지 않도록 설정되지 않도록 설정되어 있지 않은 경우, FLUSHENCEDATABASE의 명시 적 상태는 세로 상태를 확인할 수 있습니다. session.flush (); /** * 물건 제출 * 기본적으로 Commit Operation은 플러시 청소 캐시를 수행합니다. * 디스플레이없이 플러시를 호출 한 후 데이터를 롤백 할 수 없습니다. * commit * transaction.commit (); } catch (예외 e) {e.printstacktrace (); Transaction.Rollback (); } 마침내 {hibernateutils.closesession (세션); }} 중단 점을 통해 프로그램을 디버깅 할 수 있습니다.
1. 1 차 주요 사용자의 부작용은 UUID이기 때문에 Save () 메소드를 호출 한 후 사용자 객체는 세션 관리에만 포함될 수 있지만 삽입 문은 발행되지는 않지만 ID는 생성되지 않았습니다 (참고 : 저장 후 두 곳은 매우 중요합니다. 먼저 세션-> ActionQueue-> insertions-> elementData가 저장하는 요소가 있습니다. persistenceContext-> entityEntries-> map-> table-> value 객체는 값에 따라 다른 속성이 있습니다. 즉, 데이터베이스에 해당 데이터가 있는지 여부). 그림과 같이 :
2. Flush () 메소드를 호출 한 후, 세션에서 ActionQueue의 임시 저장된 값이 지워지고, PeristEnceContext의 EnsistIndAtabase의 값은 TRE로 설정되어 있으며,이 시간에 데이터베이스에 데이터베이스에 해당 데이터가 있음을 나타내지 만, 데이터를 열고 테이블을 열 때 데이터를 볼 수 없기 때문에 DataBase의 기본 분리 레벨이 제출되어 있어야합니다. 데이터. Commit () 메소드를 호출 한 후 데이터베이스에 데이터가 있습니다.
기본 키를 기본적으로 생성하는 예 :
공개 클래스 user1 {private integer uid; private string uname; private date 생일; public integer getuid () {return uid;} public void setUid (reteger uid) {this.uid = uid;} public string getUname () {return uname;} public void setuname (string uname) {}}}} 생일;} public void setbirthday (날짜 생일) {this.birthday = 생일;}}}user1.hbm.xml :
<? xml 버전 = "1.0"?> <! docType Hibernate Mapping Public "-// hibernate/hibernate 매핑 dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">-패키지 이름을 대표합니다. package = "com.lixue.bean"> <!-클래스 노드 이름은 엔티티의 클래스 이름을 나타냅니다 (맵핑 파일을 할당 할 때 클래스 이름을 수정하십시오. 그렇지 않으면 버그가 발생합니다), 테이블은 데이터베이스의 테이블에 맵핑 된 엔티티의 이름을 나타냅니다 .-> <class name = "user1"table = "t_user1"> id name = "uid"> </iD "> selverwowth"> <속성 이름 = "uname"/> <속성 이름 = "생일"/> </class> </hibernate-mapping>
테스트 방법 :
/ ***테스트 기본 1 차 키 생성 전략*/ public void testsave2 () {/*정의 세션 및 사물*/ 세션 세션 = null; 거래 거래 = null; { /*세션을 얻으십시오* / 세션 = hibernateutils.getSession (); 트랜잭션 = session.beginTransaction (); /*사용자 만들기*/ user1 user = new user1 (); user.setuname ( "li keqiang"); user.setbirthday (새 날짜 ()); / *** user1의 기본 키 생성 전략이 기본적으로, 호출 세션 () 후에 삽입 문이 실행되고 임시 수집 객체가 지워집니다.* 세션 관리에 포함 된 데이터베이스에 포함 된 데이터베이스에 의해 생성 된 ID를 반환하고, 세션에서 EndestincesIndatabase 상태를 TRUE로 수정했습니다. Transaction.commit (); } catch (예외 e) {e.printstacktrace (); Transaction.Rollback (); } 마침내 {hibernateutils.closesession (세션); }} 브레이크 포인트를 통해 프로그램 디버깅 :
1. 기본 키 생성 전략이 기본이므로 Save () 메소드를 호출 한 후 삽입 문이 실행되고 임시 수집 객체의 데이터가 지워지고 데이터베이스에서 생성 된 ID가 반환됩니다.
2. 객체를 세션 관리에 포함시키고, recistenceContext의 존재에 대한 ExistSindatabase 속성을 true로 수정하십시오 (데이터베이스에 해당 데이터가 있지만 격리 영역으로 인해 볼 수는 없음을 나타냅니다).
evict () 인 또 다른 최대 절전 모드 방법을 테스트하겠습니다. 이는 세션에서 객체를 추방하는 것을 의미합니다.
UUID 기본 키 전략을 생성하는 프로그램의 경우 다음은 테스트 방법입니다.
/ ***UUID 1 차 키 생성 전략을 테스트*/ public void testsave3 () {/*정의 된 세션 및 사물*/ 세션 세션 = null; 거래 거래 = null; { /*세션을 얻으십시오* / 세션 = hibernateutils.getSession (); 트랜잭션 = session.beginTransaction (); /*사용자 만들기*/ 사용자 user = 새 사용자 (); user.setuname ( "hu jintao"); user.setbirthday (새 날짜 ()); /*** 사용자의 주요 키 생성 전략은 UUID이므로 저장을 호출 한 후 사용자를 세션 관리에 통합하면 삽입 문을 발행하지 않지만 ID가 생성되었습니다. 세션의 EnsistIndateBase 상태는 false */ session.save (user)입니다. /*퇴거 세션에서 사용자 객체, 즉 peristenceContext*/ session.evict (user)의 EntityEntries 속성에서 추방되었습니다. /** * 동면이 캐시를 정리할 때 사용자 객체가 세션 삽입에 대한 임시 컬렉션에서 사용자 객체를 삽입 한 후 * EntityEntries 속성의 EndestenceSindAtabase는 True로 업데이트되어야하므로 세션의 엔티티 엔티티에서 사용자를 퇴거 할 수 없기 때문에 EntityEntries 속성의 EntityEntries 속성에 대한 EndatesIndatabase가 사악한 방법을 퇴거시켜야합니다. Transaction.commit (); } catch (예외 e) {e.printstacktrace (); Transaction.Rollback (); } 마침내 {hibernateutils.closesession (세션); }} 중단 점을 통한 디버깅 :
1. UUID의 기본 키 생성 전략이 사용되므로 Save () 메소드를 호출 한 후 삽입 문은 전송되지 않습니다. 객체는 세션 관리에 포함됩니다. ID가 생성되었으며 데이터베이스에 해당 데이터가 없습니다 (즉, EnsistInsindatabase 속성 값은 False).
2. evict ()을 호출 한 후, 세션에서 사용자 객체를 추방합니다.
3. Commit () 메소드를 다시 호출 할 때, 우리는 처음에 우리의 EndestenceIndatabase 속성이 거짓이기 때문에 데이터를 저장할 수 없다는 것을 알게 될 것입니다. 즉, 데이터베이스에는 해당 데이터가 없습니다. 그런 다음 evil ()을 호출하여 모든 객체 속성을 persistenceContext (EndestenceIndatabase 속성도 포함)로 삭제했지만 ActionQueue의 임시 저장된 데이터는 삭제되지 않았습니다. Commit () 메소드를 호출하면 먼저 flush () 메소드를 암시 적으로 호출합니다. 이 방법의 기능도 이전에 언급되었습니다. Actionqueue에 임시 객체를 삽입 한 다음 PeristenceContext의 EnsistSindatabase 속성 값을 True로 설정합니다. 불행히도, persistenceContext에는 사인트 사사베이스 속성이 없으므로 오류가 발생하여 저장되지 않을 수 있습니다.
이를 위해 위의 절차를 개선합니다.
/ ***UUID 1 차 키 생성 전략을 테스트*/ public void testsave4 () {/*정의 된 세션 및 사물*/ 세션 세션 = null; 거래 거래 = null; { /*세션을 얻으십시오* / 세션 = hibernateutils.getSession (); 트랜잭션 = session.beginTransaction (); /*사용자 만들기*/ 사용자 user = 새 사용자 (); user.setuname ( "hu jintao"); user.setbirthday (새 날짜 ()); /*** 사용자의 주요 키 생성 전략은 UUID이므로 저장을 호출 한 후 사용자를 세션 관리에 통합하면 삽입 문을 발행하지 않지만 ID가 생성되었습니다. persistenceContext의 EndentenceIndateBase 상태는 false */ session.save (user)입니다. / ***Flush 이후, Hibernate는 캐시를 청소하고, 사용자 객체를 데이터베이스에 저장하고, 세션의 삽입물에서 사용자 객체를 지우고, existEndatabase의 상태를 persistenceContext에서 true*/ session.flush ()로 설정합니다. / * 세션에서 사용자 객체를 퇴거시킵니다. / *** 캐시를 청소할 때 최대 절전 모드가 세션 삽입 컬렉션에있을 수 없기 때문에 성공적으로 제출할 수 있습니다.* 사용자 객체가 발견되었으므로 (플러시가 호출 될 때 지우 셨음) 삽입 문이 발행되지 않거나 세션에서 ensistIndatabase의 상태는 업데이트되지 않습니다*/ transaction.commit (); } catch (예외 e) {e.printstacktrace (); Transaction.Rollback (); } 마침내 {hibernateutils.closesession (세션); }} 참고 : 저장 후 Flush () 메소드를 호출 한 다음 수정 된 프로그램 후에 evict () 메소드를 호출합니다.
중단 점을 통한 디버깅 :
1. 여전히 UUID 생성 전략이기 때문에 저장을 호출 한 후 삽입 문은 발행되지 않지만 객체는 세션 관리에 포함됩니다. PersistEnceContext에서 존재하는 데이터베이스 속성은 False입니다.
2. Save ()을 호출 한 후 Flush () 메소드를 다시 호출합니다. 이 방법의 기능은 캐시를 청소하는 것입니다.
3. flush ()를 호출 한 후 evict () 메소드가 호출됩니다. 이 기능은 세션에서 사용자 객체를 지우는 것입니다.
4. evict () 메소드를 호출 한 후 Commit () 메소드는 flush () 메소드를 먼저 암시 적으로 호출합니다. 플러시의 기능은 캐시를 지우는 것, 즉 세션-> 삽입 임시 수집에 데이터베이스에 객체를 삽입하는 것입니다. 그러나 우리는 이전에 Flush () 메소드를 호출했습니다 (참고 :이 방법을 호출 한 후 임시 컬렉션이 지워집니다). 따라서 임시 컬렉션에는 전혀 객체가 발행되지 않습니다. 지속적으로 existincecontext로 ExistSindatabase 상태를 업데이트하지 않습니다. 성공적으로 제출하십시오.
기본 1 차 키 생성 전략에서 evict () 메소드를 사용하는 것을 고려해 봅시다.
/ ***테스트 기본 1 차 키 생성 전략*/ public void testsave5 () {/*정의 세션 및 사물*/ 세션 세션 = null; 거래 거래 = null; { /*세션을 얻으십시오* / 세션 = hibernateutils.getSession (); 트랜잭션 = session.beginTransaction (); /*사용자 만들기*/ user1 user = new user1 (); user.setuname ( "ma ying-jeou"); user.setbirthday (새 날짜 ()); / *** user1의 기본 키 생성 전략이 기본적이며, 호출 세션 () 후에 삽입 문이 실행되고, 삽입문이 실행되고, 세션 관리에 포함 된 데이터베이스에 의해 생성 된 ID를 반환하고, 세션의 EndestinceSindatabase 상태를 True로 수정하고, 데이터베이스의 격리 수준이 읽히지 않도록 설정된 경우, (사용자)를 확인할 수 있습니다. /* 세션에서 사용자 객체를 퇴거시킵니다. / *** 캐시를 청소할 때 최대 절전 모드가 세션 삽입 컬렉션에 있기 때문에 성공적으로 제출할 수 있습니다.* 사용자 객체를 찾을 수 없으므로 삽입 문은 발행되지 않거나 세션에서 ensistSindatabase의 상태가 업데이트되지 않습니다*/ transaction.commit (); } catch (예외 e) {e.printstacktrace (); Transaction.Rollback (); } 마침내 {hibernateutils.closesession (세션); }} 디버깅을 통해 :
1. 기본 키 생성 전략은 기본이므로 저장 메소드를 호출 한 후 삽입 문이 즉시 발행되어 데이터베이스에 의해 생성 된 ID를 세션 관리에 통합하고, EndestenceContext의 EndestEndatabase 속성을 PersistEnceContext의 True에 수정하고, 데이터베이스에 해당하는 데이터가 임시에 해당됩니다. 그러나 MySQL 격리 수준으로 인해 데이터를 커밋하기 전에 데이터를 볼 수 없습니다.
2. 저장을 호출 한 후, 객체가 호출되고 객체가 세션에서 추출됩니다.
3. evict () 메소드를 호출 한 후 Commit () 메소드를 성공적으로 호출 할 수 있습니다. Commit ()을 호출하기 전에 Flush () 메소드를 암시 적으로 호출하고, 즉 캐시를 정리하고 임시 컬렉션의 개체를 검색하여 데이터베이스에 삽입하기 때문에 커밋을 성공적으로 저장할 수 있습니다. 그러나 임시 컬렉션에는 데이터가 없으므로 삽입 문이 발행되지 않으며 PersistEnceContext의 EndestenceIndatabase 속성이 업데이트되지 않습니다.
위의 경우를 통해 때때로 캐시를 청소하기 위해 Flush () 메소드를 호출해야 함을 알 수 있습니다. 또한 위의 문제, 즉 데이터를 저장할 때 데이터를 제출하기 전에 데이터를 볼 수 없습니다. 즉, 데이터베이스의 격리 수준이 제한되어 있습니다. 이제 MySQL의 격리 수준에 대해 이야기 해 봅시다 :
1. MySQL 데이터베이스의 현재 격리 수준을 확인하십시오.
@@ tx_isolation을 선택하십시오;
참고 : 그림에서 MySQL 데이터베이스의 기본 격리 레벨이 반복 가능하다는 것을 알 수 있습니다. 즉, 반복 할 수없는 판독이 없음을 의미합니다. 즉, 읽기 전에 제출해야합니다.
2. MySQL의 현재 격리 수준을 수정합니다 (읽기로 제출되지 않았다고 가정합니다. 즉, 커밋없이 읽을 수 있습니다).
set transaction isolation level read uncommited;
위의 내용은 Hibernate의 Session_flush 및 격리 수준 코드에 대한 자세한 설명입니다. 모든 사람에게 도움이되기를 바랍니다. 관심있는 친구는이 사이트의 다른 관련 주제를 계속 참조 할 수 있습니다. 단점이 있으면 메시지를 남겨 두십시오. 이 사이트를 지원해 주신 친구들에게 감사드립니다!