JPA 2.1在JPA EntityListener中创建实体 [英] JPA 2.1 Create entity within JPA EntityListener

查看:147
本文介绍了JPA 2.1在JPA EntityListener中创建实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试更改或创建一个实体后立即创建一个日志条目.为了做到这一点,我在一个AbstractEntity类上注册了一个EntityListener. AbstractEntity有一个LogEntries列表,此列表的级联类型为ALL(我的所有实体都继承自AbstractEntity).

I try to create a log entry as soon as one of my entities got changed or created. In order to do this, I registered an EntityListener on an AbstractEntity class. AbstractEntity has a List of LogEntries and the cascade type of this list is ALL (all of my entities inherits from AbstractEntity).

我的EntityListener的当前实现:

Current implementation of my 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,但它也没有效果.

The problem is that the log entries are not persisted, although using cascade type all. I also tried to remove the cascade type and inject my LogEntryService (SLSB with CRUD methods) in order to persist the LogEntry manually, but it has no effect as well.

使用@PostPersist和@PostUpdate也会发生相同的问题.

Same problem occurs by using @PostPersist and @PostUpdate.

JPA提供程序是EclipseLink(2.5.0).

JPA provider is EclipseLink (2.5.0).

切换到休眠模式并使用Envers是没有选择的.

Switching to Hibernate and using Envers is no option.

推荐答案

prePersist事件应该起作用,因为在计算更改之前会调用prePersist.

The prePersist event should work, as prePersist is called before changes are computed.

对于preUpdate,此操作将不起作用,因为更改是在调用preUpdate事件之前计算出来的,因此进一步更改任何内容为时已晚.

For preUpdate this will not work as the changes are computed before the preUpdate event is called, so it is too late to change anything further.

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

You can use the EclipseLink DescriptorEvents instead, as the give you access to more advanced options. You can get the Session and call insertObject() on it directly to force the insertion of the log entry, or change the object or UnitOfWork ChangeSet.

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

Also consider EclipseLink's history support, http://wiki.eclipse.org/EclipseLink/Examples/JPA/History

EclipseLink应该提供一个执行两次通过提交的选项,以允许事件更改对象,请为此记录一个bug并对其进行投票(或查找并投票给一个现有的bug).

EclipseLink should provide an option to do a two pass commit, to allow events to change objects, please log a bug for this and vote for it (or find and vote for an existing one).

这篇关于JPA 2.1在JPA EntityListener中创建实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆