2014-09-22 63 views
0

給出的定義(爲了簡化省略IDS):在setter調用之後Hibernate是否會觸發更新查詢?

@Entity 
class A { 
    @OneToMany(mappedBy="a", cascade=CascadeType.ALL) 
    B b; 
} 

@Entity  
class B { 
    @ManyToOne 
    @JoinColumn(nullable=false) 
    A a; 
} 

而且聲明:

a.setB(b); 
b.setA(a); 
session.update(a); 
session.flush(); 

我們得到PropertyValueException在沖洗( 「非空屬性引用null或瞬時值」) 。但是,如果我們將「a.setB(b)」替換爲「b.setA(a)」,則不會引發異常。就好像「a.setB(b)」在「b.a」中使用null值觸發sql更新,而不管下一個setter和update行如何。

我們之前沒有收到過這種行爲,它顯然是從hibernate v3.6遷移到v4.3後開始的。 hibernate如何決定根據實體和會話中的實體狀態更改或方法調用來生成sql更新?有沒有可以設置的配置將其更改爲以前的行爲?

注意:這些語句被簡化了,它們之間有更多的代碼。

+0

有一些自動刷新設置...我現在不記得,但每個DML查詢後,我一直在做齊平。 – 2014-09-22 13:25:59

+0

我的flushMode是AUTO。我試着改爲COMMIT,但問題仍然存在。 – Vituel 2014-09-22 19:21:22

+0

其實我已經在web.xml(http://stackoverflow.com/a/13362558/2004857)裏面的「openSessionInViewFilter」中設置了flushMode,它沒有工作。這一次,我在sessionFactory.getCurrentSession()之後以編程方式做了它,並且異常沒有拋出。 – Vituel 2014-09-22 21:25:06

回答

0

我覺得你得到這個是因爲「或瞬態價值」。確保你從數據庫或者你告訴Hibernate來保存它,以及(或者與到persist()/update()的顯式調用)或通過創建級聯關係

0

Hibernate不會觸發一個查詢正確端來一B實例在二傳手之後,但在衝過之後。

在我的情況下,在「a.setB(b)」(而實體處於不一致的狀態:b.a == null)之後,讀操作正在觸發flush操作,因爲我在hibernate中將flushMode設置爲AUTO。

我有固定它的方式有兩種:

  1. 移動讀操作後「b.setA(一)」,當國家是一致的; 或
  2. 將flushMode設置爲COMMIT。 Note that you now have to manually flush before every db operation involving entities updated earlier in the same transaction or you might get stale data.

    Session session = sessionFactory.getCurrentSession(); 
    session.setFlushMode(FlushMode.COMMIT); 
    
+1

我想了解你是如何解決這個問題的,A和B之間有什麼樣的關係?它是一對一嗎?在你的回答中''find'是什麼意思'在我的情況下,flush是由一個find後觸發的''並且'將find移到後面'和'注意你現在必須在每次find之前手動刷新' ?因爲在hibernate會話界面中沒有find方法。在這種情況下,陳舊的數據如何產生?你能否詳細說明一下。 – Chaitanya 2014-09-23 05:09:03

+0

你是完全正確的。我已經添加了定義關係的註釋,現在它會更有意義。通過「查找」我的意思是「讀取操作」。關於flushMode和陳舊的數據,我認爲這解釋得很好:http://stackoverflow.com/a/7222097/2004857。 感謝您指出這些事情。 – Vituel 2014-09-23 12:32:14

相關問題