好消息是,Hibernate Envers按预期工作 - 版本(AUD表中的条目)不会创建,除非可修改的属性被修改。
但是,在我们的应用程序中,我们实现了一个MergeEventListener
,它在每个实体保存上更新跟踪字段(lastUpdated,lastUpdatedBy)。这导致Envers即使在没有对实体进行任何更改的情况下也可以创建新版本。
的解决办法是在年底很简单(我们) - 使用如何使用拦截器和事件由Hibernate的例子:http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/events.html
我们换成我们班实行PersistEventListener
和MergeEventListener
具有延伸EmptyInterceptor
和一类覆盖onFlushDirty和onSave方法。
public class EntitySaveInterceptor extends EmptyInterceptor {
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
setModificationTrackerProperties(entity);
return super.onFlushDirty(entity, id, currentState, previousState, propertyNames, types);
}
@Override
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
setModificationTrackerProperties(entity);
return super.onSave(entity, id, state, propertyNames, types);
}
private void setModificationTrackerProperties(Object object) {
if (SecurityContextHolder.getContext() != null && SecurityContextHolder.getContext().getAuthentication() != null) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal != null && principal instanceof MyApplicationUserDetails) {
User user = ((MyApplicationUserDetails) principal).getUser();
if (object instanceof ModificationTracker && user != null) {
ModificationTracker entity = (ModificationTracker) object;
Date currentDateTime = new Date();
if (entity.getCreatedDate() == null) {
entity.setCreatedDate(currentDateTime);
}
if (entity.getCreatedBy() == null) {
entity.setCreatedBy(user);
}
entity.setLastUpdated(currentDateTime);
entity.setLastUpdatedBy(user);
}
}
}
}
}
挂钩的EntitySaveInterceptor到Hibernate的JPA持久性单元
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="myapplication" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.ejb.interceptor" value="org.myapplication.interceptor.EntitySaveInterceptor" />
<property name="hibernate.hbm2ddl.auto" value="none"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
</persistence>
以及物品是否完整,这里是ModificationTracker接口:
public interface ModificationTracker {
public Date getLastUpdated();
public Date getCreatedDate();
public User getCreatedBy();
public User getLastUpdatedBy();
public void setLastUpdated(Date lastUpdated);
public void setCreatedDate(Date createdDate);
public void setCreatedBy(User createdBy);
public void setLastUpdatedBy(User lastUpdatedBy);
}
它也应该能够解决这个问题通过使用PreUpdateEventListener
的实现来设置ModificationTracker
值,因为该侦听器也仅在对象 是脏的。
感谢您对自己问题的回应!我面临着类似的问题,并且将更新与原始版本进行比较时遇到问题。我正在使用Hibernate MergeEventListener来设置我的跟踪列,但我的主要问题是MergeEvent“原始”对象与“实体”相同。即它已经应用了更新,因为它是一个托管对象。请你能分享你的解决方案吗? – Dagmar
抱歉,我在您发表评论时无法使用。我很高兴你找到了一个解决方案,我会编辑我的答案,包括我做了什么来纠正我的问题,但你的解决方案似乎也很好。 – Asoub