2011-02-04 163 views
11

我目前正在使用@PostPersist@PostUpdate,在這些觸發器中,我堅持附加的實體。問題是,這些觸發器是否在同一個事務中,如果不是,可以強制它嗎?JPA/@PostPersist @PostUpdate - 交易

對我而言,這是有效的。 當我查看日誌時,事務不存在(在觸發器啓動之前它已經提交),這阻止了我(沒有REQUIRES_NEW來自注入Bean的持久化方法)將其他實體保存在數據庫中。 REQUIRED屬性完全被忽略,並且MANDATORY屬性不會拋出異常。

它可能是JUnit的問題(因爲我處於開發階段,並沒有測試完整環境的行爲)?

如果延長這個觸發交易是不可能的,如何保證如果@PostPersist@PostUpdate前發生回退,這些操作也將rollbacked。

預先感謝您的任何幫助,

親切的問候, P.

+0

嘿。當我測試時,我發現監聽器中的所有操作都在主操作的同一事務中。我使用@PostUpdate註釋來標記偵聽器。 – Scarlett 2012-04-12 07:01:23

回答

11

一個PostPersist在觸發事件並不表明實體做了成功的承諾。該事務在事件發生後但在成功提交之前可以回滾。 如果您在PostPersist獲得在交易中使用的實體管理器,然後做服用點是這樣的:

@PostPersist 
void someMethod() { 
    EntityManager em = null; 
    em = getEntityManagerUsedInTransaction(); 
    EntityTransaction et = em.getTransaction(); // should return the current transaction 
    if (et.isActive()) { 
    // do more db stuff 
    } 
} 

注:我沒有嘗試過這個所以才炒作(壽」我用一生的事件觸發廣泛用於其他的東西)。 我必須補充一點,我不認爲這是一個好主意。使用PostPersist來標記其他實體應該被持久化並在另一個事務中執行。

10

如果你使用Spring,你總是可以註冊與您當前的事務管理器TransactionSynchronization被召回的事件,如您當前運行的事務的承諾:

@PostPersist 
void onPersist() { 
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { 

     @Override 
     public void beforeCommit(boolean readOnly) { 
     // do work 
     } 
    }); 
    }  
} 

一個TransactionSynchronization後還提供了回調事務已成功提交併在事務完成之前/之後提交。

如果您需要檢查交易是提交還是回滾,請使用afterCompletion(int status)

詳情看看TransactionSynchronization's JavaDoc

-1

JPA內部回調方法 內部回調方法是在實體類中定義的方法。例如,下面的實體類定義了所有支持的回調方法空的實現:

@Entity 
public static class MyEntityWithCallbacks { 
    @PrePersist void onPrePersist() {} 
    @PostPersist void onPostPersist() {} 
    @PostLoad void onPostLoad() {} 
    @PreUpdate void onPreUpdate() {} 
    @PostUpdate void onPostUpdate() {} 
    @PreRemove void onPreRemove() {} 
    @PostRemove void onPostRemove() {} 
} 

內部回調方法應該總是返回void,並且沒有參數。他們可以有任何名稱和任何訪問級別(公共,受保護,包和私有),但不應該是靜態的。

的註釋指定時調用的回調方法:

@PrePersist - before a new entity is persisted (added to the EntityManager). 
@PostPersist - after storing a new entity in the database (during commit or flush). 
@PostLoad - after an entity has been retrieved from the database. 
@PreUpdate - when an entity is identified as modified by the EntityManager. 
@PostUpdate - after updating an entity in the database (during commit or flush). 
@PreRemove - when an entity is marked for removal in the EntityManager. 
@PostRemove - after deleting an entity from the database (during commit or flush). 

實體類可以包括用於任何子集或生命週期事件的組合,但沒有爲同一事件多於一個回調方法回調方法。但是,通過用多個註釋標記多個回調事件,可以使用同一方法。

默認情況下,還會爲子類的實體對象調用超類實體類中的回調方法,除非該子類重寫該回調方法。

實施限制 爲避免觸發實體生命週期事件(仍在進行中)的原始數據庫操作發生衝突,回調方法不應調用EntityManager或Query方法,也不應訪問任何其他實體對象。

如果回調方法在活動事務中拋出異常,則事務被標記爲回滾,並且不會爲該操作調用更多回調方法。