2012-10-05 155 views
3

我對春節@Transactional註解和堅持的誤解。我正在使用Spring 3.1,使用JPA和Hibernate。我認爲persist意味着,將實體添加到持久性上下文中(但不要執行任何查詢,直到提交或刷新),並且註釋的含義是用事務包裝該方法。春季交易註釋,休眠和堅持

但是,在這個簡短的例子中,當執行指針到達時,由於名稱不能爲空(db約束),所以它會失敗併產生異常。

import javax.persistence.EntityManager; 

@PersistenceContext 
private EntityManager entityManager; 

@Transactional 
public void test() { 
    Brand brand = new Brand(); 
    entityManager.persist(brand); 
    brand.setName("test"); 
} 

如果我換setName()persist(),一切正常。然而,我不明白爲什麼其他解決方法不會這樣,因爲我認爲任何查詢都會在方法結束時生成並執行。

有人能解釋一下嗎?

回答

4

在JPA中,一旦對象傳遞給persist(),它就變成了「託管」,作爲託管JPA實現的一部分,必須爲該持久對象生成一個id。

如果id生成基於自動增量(GenerationType.IDENTITY),則需要向db發出insert語句來獲取和分配鍵。當id生成基於sequence/table時,id由JPA Implementation管理標識池管理和分配,在這種情況下,不需要直接插入。

讓一個對象傳遞給persist()併成爲託管對象,對其進行的任何更改都必須將持久字段刷新到事務處理中的數據庫。在你的情況下,如果身份證號是身份,則必須在更新後執行插入操作。如果id生成是其他方法,那麼只需一個插入語句即可。如果事務回滾,則根本不應該將SQL發送到數據庫。

這是在Batoo JPA中的實現。

希望這是有道理的。

+0

有趣,有道理,現在我明白了,實際上我有GenerationType.IDENTITY。謝謝 – stivlo

2

它的承諾由於事務性註釋的方法結束。但是新記錄是持續創建的,並且可以拋出任何異常。

在方法結束之前,它仍然可以回滾;我通常使用回滾來註釋異常。

0

堅持執行「插入」查詢。事務註釋僅用於啓動事務,如果發生異常,則回滾事務。