Hibernate JPA 6.2.x failure on ConcurrentModificationException

160 Views Asked by At

Environment: Spring boot 3.1.x, Hibernate 6.2.x

Our JPA repository implementations are like this:

    @Transactional
    public interface MyEntityRepository extends JpaRepository<MyEntity, String> {
        List<MyEntity> findAllByIntegrationId(String integrationId);
    }

The entity class:

    @Entity
    @Table(name = "......")
    public class MyEntity {
        private String integrationId;
        ......

        public String getIntegrationId() {
            return integrationId;
        }

        public void setIntegrationId(String integrationId) {
            this.integrationId = integrationId;
        }
    }

or

    @Repository
    public interface MyTaskRepository extends JpaRepository<MyTask, String> {
        MyTask findFirstByIntegrationIdOrderByStartedDesc(String integrationId);
    }
  • There is no issue when calling such JPA repository method in single thread.
  • There is no issue when calling such method in multiple threads if the method has already been executed before.
  • But it fails for such call in multiple threads, if: such JPA repository call has never been called before; and multiple threads executing the call at the same time.
  • So far we observed the failure in hibernate versions '6.2.6.Final' and '6.2.7.Final'.
  • It does not fail in these hibernate versions: '6.2.2.Final' and '6.2.8.Final'.

Does anyone know a hibernate JPA 6.2.x issue like this which was fixed in '6.2.8.Final'? We want get confirmation that it's truly fixed in the latest hibernate JPA, not just accidentally hidden and might show up later.

  • Here is the exception stacktrace:

java.util.ConcurrentModificationException: null

  • at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
  • at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitAnsiCaseSearchedExpression(AbstractSqlAstTranslator.java:6433)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitCaseSearchedExpression(AbstractSqlAstTranslator.java:6424)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitCaseSearchedExpression(AbstractSqlAstTranslator.java:6416)
  • at org.hibernate.sql.ast.tree.expression.CaseSearchedExpression.accept(CaseSearchedExpression.java:99)
  • at org.hibernate.metamodel.mapping.internal.CaseStatementDiscriminatorMappingImpl$CaseStatementDiscriminatorExpression.renderToSql(CaseStatementDiscriminatorMappingImpl.java:278)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSelfRenderingExpression(AbstractSqlAstTranslator.java:6657)
  • at org.hibernate.sql.ast.tree.expression.SelfRenderingExpression.accept(SelfRenderingExpression.java:20)
  • at org.hibernate.dialect.PostgreSQLSqlAstTranslator.renderExpressionAsClauseItem(PostgreSQLSqlAstTranslator.java:64)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.renderSelectExpression(AbstractSqlAstTranslator.java:5020)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelectExpression(AbstractSqlAstTranslator.java:5015)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelection(AbstractSqlAstTranslator.java:4997)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSqlSelections(AbstractSqlAstTranslator.java:4662)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSelectClause(AbstractSqlAstTranslator.java:4563)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitQuerySpec(AbstractSqlAstTranslator.java:3031)
  • at org.hibernate.dialect.PostgreSQLSqlAstTranslator.visitQuerySpec(PostgreSQLSqlAstTranslator.java:186)
  • at org.hibernate.sql.ast.tree.select.QuerySpec.accept(QuerySpec.java:119)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.visitSelectStatement(AbstractSqlAstTranslator.java:986)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.translateSelect(AbstractSqlAstTranslator.java:849)
  • at org.hibernate.sql.ast.spi.AbstractSqlAstTranslator.translate(AbstractSqlAstTranslator.java:799)
  • at org.hibernate.loader.ast.internal.CollectionLoaderSingleKey.load(CollectionLoaderSingleKey.java:106)
  • at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:680)
  • at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:75)
  • at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
  • at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1702)
  • at org.hibernate.collection.spi.AbstractPersistentCollection.lambda$initialize$3(AbstractPersistentCollection.java:617)
  • at org.hibernate.collection.spi.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:265)
  • at org.hibernate.collection.spi.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:615)
  • at org.hibernate.collection.spi.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:813)
  • at org.hibernate.engine.internal.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:985)
  • at org.hibernate.engine.internal.StatefulPersistenceContext.initializeNonLazyCollections(StatefulPersistenceContext.java:971)
  • at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:227)
  • at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33)
  • at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:361)
  • at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:168)
  • at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.list(JdbcSelectExecutorStandardImpl.java:93)
  • at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:31)
  • at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$0(ConcreteSqmSelectQueryPlan.java:110)
  • at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:303)
  • at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:244)
  • at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:518)
  • at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:367)
  • at org.hibernate.query.Query.getResultList(Query.java:119)
  • at org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution.doExecute(JpaQueryExecution.java:129)
  • at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92)
  • at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:148)
  • at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:136)
  • at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
  • at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
  • at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164)
  • at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
  • at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
  • at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
  • at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
  • at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
  • at jdk.proxy2/jdk.proxy2.$Proxy205.findAllByIntegrationId(Unknown Source)

Summery: Call JPA repository method concurrently the first time and fail.

0

There are 0 best solutions below