JPA 2.1 Create entity within JPA EntityListener

你说的曾经没有我的故事 提交于 2021-01-28 14:54:45

问题


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).

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

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.

Same problem occurs by using @PostPersist and @PostUpdate.

JPA provider is EclipseLink (2.5.0).

Switching to Hibernate and using Envers is no option.


回答1:


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

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.

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.

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

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).



来源:https://stackoverflow.com/questions/18464697/jpa-2-1-create-entity-within-jpa-entitylistener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!