问题
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