在 Hibernate Envers 中丢弃修订版
Discard revision in Hibernate Envers
实体在某些情况下不需要保存修改,请问如何处理?我只想跳过修订的创建,已经审查过源代码,没有机会。
如果您尝试在自定义 EnversPostInsertEventListenerImpl 中进行数据库更改,例如,在同一事务中进行调用(在 onPostInsert 中):
PersistedProperty property = dao.findClass(PersistedProperty.class, "where propertyTemplate.id = ? and fileEntry.id = ?",
propertyTemplate.getId(), f.getId());
String v = convertObject2String(propertyTemplate, value);
if (property == null) {
property = new PersistedProperty(propertyTemplate, v, f);
} else {
property.setValue(v);
}
dao.merge(property);
然后你会得到下一个异常:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.Collections$UnmodifiableCollection.next(Collections.java:1042)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:587)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
问题是在 AbstractSaveEventListener 中深度重复 ActionQueue 的相同实例(第 318 行)以及内部事务对 ActionQueue 的最终修改。
在文档中,有一个名为 Conditional Auditing 的部分对此进行了讨论。
基本概念是您需要覆盖 Envers 注册的 Hibernate 事件侦听器,以使用您自己的自定义实现来处理触发审计。
您的实施基本上需要扩展 Envers 侦听器并且:
- 检查事件是否针对您有兴趣跳过的实体类型。
- 检查修改后的状态,看看是否只发生了暗示跳过的情况。
- 如果你想跳过,干脆不要委托给超级实现。
如果您使用 ValidityAuditStrategy
而不是 DefaultAuditStrategy
,我强烈建议您避免对 INSERT
操作使用条件审计。
据我所知,对 UPDATE
操作使用条件审计是可行的,但在原始插入上这样做会导致永远不会添加 ADD
行,因此ValidityAuditStrategy
将在您尝试审计该实体行的第一个 UPDATE
时断言。
Hibernate 6 的目标是超越用户为条件审计操作事件侦听器的需要,转向更像 JPA 事件侦听器注释的方法。有关详细信息,请参阅 HHH-11326。
实体在某些情况下不需要保存修改,请问如何处理?我只想跳过修订的创建,已经审查过源代码,没有机会。
如果您尝试在自定义 EnversPostInsertEventListenerImpl 中进行数据库更改,例如,在同一事务中进行调用(在 onPostInsert 中):
PersistedProperty property = dao.findClass(PersistedProperty.class, "where propertyTemplate.id = ? and fileEntry.id = ?",
propertyTemplate.getId(), f.getId());
String v = convertObject2String(propertyTemplate, value);
if (property == null) {
property = new PersistedProperty(propertyTemplate, v, f);
} else {
property.setValue(v);
}
dao.merge(property);
然后你会得到下一个异常:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at java.util.Collections$UnmodifiableCollection.next(Collections.java:1042)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:587)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1435)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3201)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2411)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:467)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:146)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access0(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:220)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
问题是在 AbstractSaveEventListener 中深度重复 ActionQueue 的相同实例(第 318 行)以及内部事务对 ActionQueue 的最终修改。
在文档中,有一个名为 Conditional Auditing 的部分对此进行了讨论。
基本概念是您需要覆盖 Envers 注册的 Hibernate 事件侦听器,以使用您自己的自定义实现来处理触发审计。
您的实施基本上需要扩展 Envers 侦听器并且:
- 检查事件是否针对您有兴趣跳过的实体类型。
- 检查修改后的状态,看看是否只发生了暗示跳过的情况。
- 如果你想跳过,干脆不要委托给超级实现。
如果您使用 ValidityAuditStrategy
而不是 DefaultAuditStrategy
,我强烈建议您避免对 INSERT
操作使用条件审计。
据我所知,对 UPDATE
操作使用条件审计是可行的,但在原始插入上这样做会导致永远不会添加 ADD
行,因此ValidityAuditStrategy
将在您尝试审计该实体行的第一个 UPDATE
时断言。
Hibernate 6 的目标是超越用户为条件审计操作事件侦听器的需要,转向更像 JPA 事件侦听器注释的方法。有关详细信息,请参阅 HHH-11326。