2013-08-27 171 views
1

我嘗試在一個實體被更改或創建後立即創建一個日誌條目。爲了做到這一點,我在AbstractEntity類上註冊了一個EntityListener。 AbstractEntity有一個LogEntries列表,這個列表的級聯類型是ALL(我的所有實體都繼承自AbstractEntity)。JPA 2.1在JPA EntityListener中創建實體

當前實現我EntityListener的:

public class EntityChangeListener { 

    @Inject 
    SessionController sessionController; 

    @PreUpdate 
    public void preUpdate(AbstractEntity entity) { 
     createLogEntryFor(entity, LogEntry.ChangeType.UPDATED); 
    } 

    @PrePersist 
    public void prePersist(AbstractEntity entity) { 
     createLogEntryFor(entity, LogEntry.ChangeType.CREATED); 
    } 

    private void createLogEntryFor(AbstractEntity entity, LogEntry.ChangeType changeType) { 
     if (!(entity instanceof LogEntry)) { 
      Date now = Calendar.getInstance().getTime(); 
      LogEntry logEntry = new LogEntry(); 
      logEntry.setCreator(sessionController.getCurrentUser()); 
      logEntry.setAbstractEntity(entity); 
      logEntry.setChangeDate(now); 
      logEntry.setChangeType(changeType); 
      entity.getLogEntries().add(logEntry); 
     } 
    } 
} 

的問題是,日誌條目不會保留,雖然使用級聯輸入所有。我也嘗試刪除級聯類型並注入我的LogEntryService(帶有CRUD方法的SLSB)以便手動持久化LogEntry,但它也沒有效果。

通過使用@PostPersist和@PostUpdate發生同樣的問題。

JPA提供者是EclipseLink(2.5.0)。

切換到休眠狀態並使用Envers是沒有選擇的。

回答

1

prePersist事件應該起作用,因爲在計算更改之前調用prePersist。

對於preUpdate,這將不起作用,因爲更改是在調用preUpdate事件之前計算的,所以更改任何事情爲時已晚。

您可以改爲使用EclipseLink DescriptorEvents,因爲您可以訪問更多高級選項。您可以直接獲取Session並調用insertObject()來強制插入日誌條目,或者更改對象或UnitOfWork ChangeSet。

還要考慮的EclipseLink的歷史支持, http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

的EclipseLink應該提供一個選項,做一個雙向承諾,使得事件能夠改變物體,請登錄了這一點,並投贊成票的錯誤(或查找和投票對於現有的)。

+0

好的,但只要我使用DescriptorEvents,我必須執行檢查實體是否發生了變化,並且我失去了JPA 2.1在Entitylisteners中注入CDI Beans的強大新功能。對? – mare