2011-11-21 76 views
2

我越來越奇怪的問題。我的問題是使用EJB 3.0jboss 5.1.0.GAEJB 3.0更新然後選擇不正常工作jboss5.1.0.G

Subscriber s = (Subscriber)manager.createQuery("SELECT s FROM Subscriber s " + 
     "WHERE s.subscriber_id = ?1").setParameter(1,123).getSingleResult(); 

然後我做更新到實體查詢這樣

int a = manager.createQuery(" UPDATE Subscriber s SET s.balance = s.balance + "+10+"WHERE s.subscriber_id = ?1").setParameter(1,123).executeUpdate(); 

THEN againg我從數據庫中該

FIRST時選擇實體選擇像這樣的實體

s = (Subscriber)manager.createQuery("SELECT s FROM Subscriber s " + 
"WHERE s.subscriber_id = ?1").setParameter(1,123).getSingleResult(); 

但我沒有得到「餘額」字段的更新值,但只要我評論第一個SELECT聲明我正在獲取更新值。但是無論如何我需要第一個SELECT聲明,因爲我想使用它。

任何人都可以告訴我爲什麼會發生,它的解決方案是什麼?

回答

1

我敢打賭,這是因爲緩存問題。

我會假設你的manager是一個EntityManager實例。

您正在執行第一個查詢,因此PersistenceContext正在從數據庫中提取Subscriber實體並將其放入緩存中。然後,您正在執行批量更新查詢,它直接命中數據庫忽略緩存結構,因此它不會影響PersistenceContext。
最後,您再次執行SELECT查詢。這樣做,PersistenceContext檢查是否有Subscribe實體緩存在某處。它的確如此,因此它不會觸及數據庫,但會返回緩存中存儲的值。

我不完全明白你爲什麼要執行批量更新查詢,而不僅僅是更新你的對象狀態,並讓JPA在適當的時候提交更改。

所以不是:

int a = manager.createQuery("UPDATE Subscriber s SET s.balance = s.balance + 
          "+10+"WHERE s.subscriber_id = ?1") 
       .setParameter(1,123).executeUpdate(); 

你可能只是做:

// 's' is the Subscribe entity previously fetched from the database 
s.setBalance(s.getBalance() + 10); 

但如果你仍然真的需要使用巴赫UPDATE,那麼你可以嘗試做

manager.refresh(s); 

批量更新查詢後。這將讓JPA訪問數據庫而不是其緩存版本。

如果您評論第一個SELECT語句,該示例將工作,因爲PersistenceContext沒有緩存您的實體。它在批量UPDATE查詢後第一次從數據庫中提取它。

+0

非常感謝Piotr Nowicki。它的工作................ –

+0

如果它的工作和回答你的問題,隨時接受這個答案。 –