2013-08-27 122 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