好消息是,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