2013-01-15 19 views
1

我有以下代碼的等效代碼和Hibernate配置(基本上,StreamRef屬於磁帶,並且必須在該磁帶上唯一的):Hibernate如何能夠拋出NonUniqueObjectException與setCacheMode(CacheMode.IGNORE)?

<class name="StreamRef" table="StreamRefToTape"> 
<composite-id> <key-property name="UUID"/> 
    <key-many-to-one class="Tape" name="tape"> 
    <column name="Tape_TapeId" not-null="true"/> 
    </key-many-to-one> 
</composite-id> 
...</class> 

<class name="Tape" table="Tape"> 
<id column="TapeId" name="tapeId"/></class> 

我有幾百萬,這些StreamRef的,我要保存他們都在同一個事務中,但我也想在這個事務中保存RAM。

所以我嘗試了下面的代碼,我的假設是如果我關閉CacheMode,那麼它不會在內部跟蹤對象,所以它會節省很多內存(這在某種程度上似乎有所幫助)。但在測試這個假設的時候,是這樣的:

session = sessionFactory.openSession(); 
session.setCacheMode(CacheMode.IGNORE); // disable the first level cache 
session.beginTransaction(); 
Tape t = new Tape(); 
StreamRef s1 = new StreamRef("same uuid"); 
StreamRef s2 = new StreamRef("same uuid"); // force a primary key collision 
session.saveOrUpdate(t); 
for(StreamRef s : t.getStreams()) { 
    session.save(s); 
} 
session.commit(); 

我本來期望這提價,是因爲我關掉CacheMode參數(但它提出了一個NonUniqueObjectException https://gist.github.com/4542569)。有人可以確認1)休眠內部緩存是而不是禁用? 2)這個異常與CacheMode無關?有什麼辦法來完成我想在這裏

有點關係(在事務中未用完噸休眠RAM的?):https://stackoverflow.com/a/3543740/32453

(作爲一個方面的問題......這很重要的順序setCacheMode被稱爲vin與beginTransaction的關係?我認爲它不?)

非常感謝。

+0

如果使用'session.merge()'而不是'session.save()' – Charlie

+0

以及某種程度的合併,相等檢查比較失敗。嗯... https://gist.github.com/4542563 – rogerdpack

回答

1

這個例外是有道理的。你違反了你告訴Hibernate你要玩的規則。如果你真的想做你編碼的事情,你需要使用StatelessSession API或createSQLQuery API。就目前而言,Session.setCacheMode用於與二級緩存交互,而不是會話緩存。

關於內存使用情況,您需要逐步將批量記錄刷新到磁盤,以便Hibernate可以清除其ActionQueue

這裏是從批量更新部分中的user's guide一個例子:

Session session = sessionFactory.openSession(); 
Transaction tx = session.beginTransaction(); 

for (int i=0; i<100000; i++) { 
    Customer customer = new Customer(.....); 
    session.save(customer); 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of inserts and release memory: 
     session.flush(); 
     session.clear(); 
    } 
} 

tx.commit(); 
session.close(); 

你也可以閱讀有關在同一章無狀態的會話。

+0

真棒高質量的答案,謝謝!我想因爲我在我的hibernate.cfg.xml中指定了 org.hibernate.cache.NoCacheProvider,無論如何,我設置緩存模式並不重要,總之,是一次失敗的初始嘗試。謝謝! 另一個選擇是做(週期性或每個元素)flush(),然後是我添加的每個項目的驅逐(這與clear()相同我想象,列表的方式允許批量插入,以及)。 – rogerdpack

1

Hibernate將一次保存所有會話對象......緩存將存儲其他會話的對象...所以你不能禁用你的單一會話......你不能這樣做嘗試使用合併( )....

相關問題