I’m using Hibernate envers for auditing, and most of my tables are performing batch inserts just fine. However, on one of my entities I have an audited collection, which seems like it doesnt want to batch.
MyEntity:
@Entity @DynamicUpdate @Indexed(index = "aj") @JsonInclude(JsonInclude.Include.NON_NULL) public class ElementGroup { ... @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.DETACH, CascadeType.MERGE }) @BatchSize(size = 30) @OrderBy("id ASC") @JoinTable( name = "element_groups", joinColumns = @JoinColumn(name = "group_id"), inverseJoinColumns = @JoinColumn(name = "member_id") ) @Audited protected List<Element> members = new LinkedList<Element>();
(Not sure if this is important, Im using postgresql). In the logs I see 1000s of these statements in a loop
DEBUG 2021-11-07 15:28:56,673 [applicationInterfcePublishTaskExecuter-4::o.h.SQL.logStatement] [user:system] insert into nst_netobj_groups_aud (revtype, revend, rev, group_id, member_id) values (?, ?, ?, ?, ?) DEBUG 2021-11-07 15:28:56,677 [applicationInterfcePublishTaskExecuter-4::o.h.SQL.logStatement] [user:system] select nst_netobj0_.rev as rev1_137_, nst_netobj0_.group_id as group_id2_137_, nst_netobj0_.member_id as member_i3_137_, nst_netobj0_.revtype as revtype4_137_, nst_netobj0_.revend as revend5_137_ from nst_netobj_groups_aud nst_netobj0_ where nst_netobj0_.group_id=? and nst_netobj0_.member_id=? and ( nst_netobj0_.revend is null ) for update of nst_netobj0_
Doing some debugging, I’ve understood that the select for update statement is causing the flush of the previous insert, not allowing them to batch. This line seems to be the reason:
final List<Object> l = qb.toQuery( session ).setLockOptions( LockOptions.UPGRADE ).list(); hibernate-envers-5.4.27.Final-sources.jar!/org/hibernate/envers/strategy/internal/ValidityAuditStrategy.java:328
I see that setting flush mode to Manual/Commit doesnt seem to help. Any suggestions?
Full stack trace:
logStatement:125, SqlStatementLogger (org.hibernate.engine.jdbc.spi) prepareStatement:170, StatementPreparerImpl$StatementPreparationTemplate (org.hibernate.engine.jdbc.internal) prepareQueryStatement:151, StatementPreparerImpl (org.hibernate.engine.jdbc.internal) prepareQueryStatement:2104, Loader (org.hibernate.loader) executeQueryStatement:2041, Loader (org.hibernate.loader) executeQueryStatement:2019, Loader (org.hibernate.loader) doQuery:948, Loader (org.hibernate.loader) doQueryAndInitializeNonLazyCollections:349, Loader (org.hibernate.loader) doList:2850, Loader (org.hibernate.loader) doList:2832, Loader (org.hibernate.loader) listIgnoreQueryCache:2664, Loader (org.hibernate.loader) list:2659, Loader (org.hibernate.loader) list:506, QueryLoader (org.hibernate.loader.hql) list:400, QueryTranslatorImpl (org.hibernate.hql.internal.ast) performList:219, HQLQueryPlan (org.hibernate.engine.query.spi) list:1414, SessionImpl (org.hibernate.internal) doList:1625, AbstractProducedQuery (org.hibernate.query.internal) list:1593, AbstractProducedQuery (org.hibernate.query.internal) performCollectionChange:328, ValidityAuditStrategy (org.hibernate.envers.strategy.internal) performCollectionChange:76, AuditStrategy (org.hibernate.envers.strategy) perform:87, PersistentCollectionChangeWorkUnit (org.hibernate.envers.internal.synchronization.work) executeInSession:125, AuditProcess (org.hibernate.envers.internal.synchronization) doBeforeTransactionCompletion:164, AuditProcess (org.hibernate.envers.internal.synchronization) doBeforeTransactionCompletion:47, AuditProcessManager$1 (org.hibernate.envers.internal.synchronization) beforeTransactionCompletion:954, ActionQueue$BeforeTransactionCompletionProcessQueue (org.hibernate.engine.spi) beforeTransactionCompletion:525, ActionQueue (org.hibernate.engine.spi) beforeTransactionCompletion:2381, SessionImpl (org.hibernate.internal) beforeTransactionCompletion:447, JdbcCoordinatorImpl (org.hibernate.engine.jdbc.internal) beforeCompletionCallback:183, JdbcResourceLocalTransactionCoordinatorImpl (org.hibernate.resource.transaction.backend.jdbc.internal) access$300:40, JdbcResourceLocalTransactionCoordinatorImpl (org.hibernate.resource.transaction.backend.jdbc.internal) commit:281, JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl (org.hibernate.resource.transaction.backend.jdbc.internal) commit:101, TransactionImpl (org.hibernate.engine.transaction.internal) doCommit:562, JpaTransactionManager (org.springframework.orm.jpa) processCommit:743, AbstractPlatformTransactionManager (org.springframework.transaction.support) commit:711, AbstractPlatformTransactionManager (org.springframework.transaction.support) execute:152, TransactionTemplate (org.springframework.transaction.support) lambda$publishApplicationInterfaceAsync$0:298, ApplicationInterfaceService (com.tufin.secureapp.service.interfaces) run:-1, 16579879 (com.tufin.secureapp.service.interfaces.ApplicationInterfaceService$$Lambda$669) runWorker:1149, ThreadPoolExecutor (java.util.concurrent) run:624, ThreadPoolExecutor$Worker (java.util.concurrent) run:748, Thread (java.lang)
Advertisement
Answer
I checked it out, and here’s what I found:
- Chris, who’s been doing most of Envers fixes during my time as a Hibernate dev, wrote this reply telling that there’s no workaround at the moment
- there’s the HHH-14664 issue created for this problem, but no one provided a fix for it.
So, until someone fixes [HHH-14664], the only option would be to provide a CustomValidityAuditStrategy
that extends the ValidityAuditStrategy
and fixes the issue.