下面是我剛碰到的另一個原因:在同一事務中多次調用存儲過程時緩存以前的結果。簡化代碼如下。
//Begin transaction
SessionFactory sf = HibernateSessionFactory.getFactory();
Session dbSession = sf.getCurrentSession();
dbSession.beginTransaction();
//First call to stored procedure
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA");
query.setString("custName", "A");
List<ShipSummaryRow> shipSummaryRows = query.list();
//Second call to stored procedure
Query query = dbSession.getNamedQuery("RR_CUST_OPP_DATA");
query.setString("custName", "B");
List<ShipSummaryRow> shipSummaryRows = query.list();
//Commit both
dbSession.getTransaction().commit();
第一次調用後沒有clear(),第一次調用的結果集行被複制到第二次調用的結果集中。我正在使用Oracle 11gR2。
複製此錯誤的關鍵是在同一個事務中進行兩個調用。由於我在視圖模式中使用了開放會話,因此兩個調用都會在同一個事務中自動發生(因爲原始代碼在循環中調用每個結果的循環)。因此我把它稱爲一個bug。否則可能被認爲是一個功能,但即使這樣clear()也不會在代碼示例中調用,並聲明它應該被調用。 session.flush()什麼都沒做。 映射文件如下。因此,我已將clear()添加到所有過程調用的末尾。尚未用我的自定義SQL調用進行測試。這是微不足道的東西;驚訝存在的錯誤。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.jfx.rr.model.ShipSummaryRow">
<id name="id" type="integer"/>
<property name="shipQtrString" not-null="true" type="string"/>
<property name="shipAmount" not-null="true" type="double"/>
</class>
<sql-query callable="true" name="RR_CUST_OPP_DATA">
<return class="com.jfx.rr.model.ShipSummaryRow">
<return-property column="SHIPPED_ID" name="id"/>
<return-property column="SHIP_QTR" name="shipQtrString"/>
<return-property column="SHIPPED_AMOUNT" name="shipAmount"/>
</return>
{ call RR_DASHBOARD_REPORTS_PKG.RR_CUST_OPP_DATA(?, :custName) }
</sql-query>
</hibernate-mapping>
ad A):在一個事務中處理大型數據集聽起來像是糟糕的設計給我的(理所當然,我可能沒有想到所有可能的問題......)。 「明確」堅持一個實體是什麼意思? session.save(實體)? Ad C):聽起來我們同意框架不應該這樣做 - 框架不可能確定客戶端做了什麼。 :-) –
@MortenLauritsenKhodabocus:顯然,在一個Hibernate事務中加載和修改數千條記錄是一個標誌,應該使用不同的工具。是的,通過*顯式*我的意思是調用'save()'而不是讓Hibernate發現髒實體。 –
@MortenLauritsenKhodabocus請賜教。爲什麼在一個事務中處理一個大型的只讀數據集是一個壞主意?在我看來,如果它涉及在數據庫方面訂購,它會很聰明,因爲它可以節省多次重新訂購。不使用事務意味着數據庫將記住您作爲同一事務的不同查詢的訂購狀態?另外,Hibernate's ScrollableResults API的功能不是「使用一個事務」嗎? – KyleM