JPA 2.1在JPA EntityListener中创建实体

时间:2013-08-27 11:56:23

标签: java jpa eclipselink entitylisteners jpa-2.1

一旦我的某个实体被更改或创建,我就会尝试创建一个日志条目。为此,我在AbstractEntity类上注册了一个EntityListener。 AbstractEntity有一个LogEntries列表,这个列表的级联类型是ALL(我的所有实体都继承自AbstractEntity)。

我的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);
        }
    }
}

问题是日志条目不会保留,尽管使用cascade类型all。我还尝试删除级联类型并注入我的LogEntryService(带有CRUD方法的SLSB)以便手动保留LogEntry,但它也没有效果。

使用@PostPersist和@PostUpdate会出现同样的问题。

JPA提供程序是EclipseLink(2.5.0)。

切换到Hibernate并使用Envers是没有选择。

1 个答案:

答案 0 :(得分:1)

prePersist事件应该有效,因为在计算更改之前会调用prePersist。

对于preUpdate,这将不起作用,因为在调用preUpdate事件之前计算了更改,因此更改任何内容为时已晚。

您可以使用EclipseLink DescriptorEvents,因为您可以访问更高级的选项。您可以直接获取Session并调用insertObject()以强制插入日志条目,或更改对象或UnitOfWork ChangeSet。

还要考虑EclipseLink的历史支持, http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

EclipseLink应提供执行双向提交的选项,以允许事件更改对象,请为此记录错误并为其投票(或查找并投票选择现有的)。