我得到這個應用程序,它所做的是執行選擇,並在讀完後我不再需要該對象。休眠:讀取後刪除存儲在堆中的選定數據
因爲查詢是非常原子的,所以我沒有問題讀取數據。我的問題是那裏的數據量很大,因此最終在堆中存儲的舊對象導致內存不足異常。
我該如何執行選擇,擺脫以前的對象?
我得到這個應用程序,它所做的是執行選擇,並在讀完後我不再需要該對象。休眠:讀取後刪除存儲在堆中的選定數據
因爲查詢是非常原子的,所以我沒有問題讀取數據。我的問題是那裏的數據量很大,因此最終在堆中存儲的舊對象導致內存不足異常。
我該如何執行選擇,擺脫以前的對象?
的對象將由NH會話緩存被引用。要擺脫他們,你可以
Clear
會話(這也從會話中刪除其他對象)Evict
每個對象select a, b
或select new Dto(a, b)
)。不引用它們的對象將被垃圾收集,並且不會導致內存不足異常。所以,如果你確實得到這樣的異常,那麼對象仍然被引用,你需要找出它們是什麼。
如果錯誤是由過大的結果集引起的,則可以考慮通過setMaxResults()
和setFirstResult()
或Query.iterate()使用分頁。
沒關係,這意味着在理論上,如果我有一個10點的對象,每1000個乙對象的集合,它應該收集對象1001的10倍? – javaNoober
在每個對象中有10個對象和1000個B對象,您可能只需要增加堆大小。如果你有幾百萬個B對象上有幾百萬個A對象,那將會更棘手。在這種情況下,您可能需要遍歷列表或獲取頁面,例如1000個對象。您可能還需要驅逐您按照其他答案中的建議處理的對象。 'scroll'也是一件好事。 –
是的,我有數百萬,只是懶與零,thx – javaNoober
在完成與您查詢的實體的工作後,您應該從會話緩存中將其逐出,然後將其解除引用,此時它將符合垃圾回收的條件。請參閱Hibernate指南中標題爲Managing the Caches的部分中的示例。這裏有一個例子:
ScrollableResult cats = sess.createQuery("from Cat as cat").scroll(); //a huge result set
while (cats.next()) {
Cat cat = (Cat) cats.get(0);
doSomethingWithACat(cat);
sess.evict(cat);
}
奇怪的事情,我創建我的entityManager一次,然後我在其他調用返回相同的EM。如果我得到一個會議指出的EntityManager的會話是空 – javaNoober
如果您使用JPA 2.0,你應該叫EntityManager.detach(對象),而不是session.evict()。否則,調用EntityManager.getDelegate,將其轉換爲Session並使用evict。 –
我會試着稍後分離。只是不明白,爲什麼我的(會議)getDelegate是空已經和MTA轉儲說的對象仍然存在 – javaNoober
我相信我的整個問題是設計我對這個桌面應用程序(這似乎是自動的session-per-線程情況),StatelessSession看起來不錯 – javaNoober