Affects: Spring Orm: 5.3.14 Spring boot version: 2.6.2 Spring data jpa: 2.6.0 Spring Integration version: 5.5.6

Issue: Seems like JPATransactionManager and HibernateJpaDialect cannot transform a org.hibernate.TransactionException to the right JPA exception based on the internal SQLException, as you can see in the following stacktrace:

Caused by: org.springframework.dao.CannotAcquireLockException: Failed to lock mutex at 19414b49-c76b-3b77-a05d-3aca07a855aa; nested exception is org.springframework.orm.jpa.JpaSystemException: Unable to commit against JDBC Connection; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection
    at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.rethrowAsLockException(JdbcLockRegistry.java:197)
    at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.tryLock(JdbcLockRegistry.java:262)
    at com.geniussports.geniuslive.ingressmanager.domain.pipeline.ingress.IngressPipelineService.create(IngressPipelineService.kt:35)
    at com.geniussports.geniuslive.ingressmanager.application.adapters.pipeline.ingress.gateway.graphql.PipelineMutationResolver.createFromJSON(PipelineMutationResolver.kt:51)
    at jdk.internal.reflect.GeneratedMethodAccessor254.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282)
    at com.netflix.graphql.dgs.internal.DgsSchemaProvider.invokeDataFetcher(DgsSchemaProvider.kt:402)
    at com.netflix.graphql.dgs.internal.DgsSchemaProvider.access$invokeDataFetcher(DgsSchemaProvider.kt:64)
    at com.netflix.graphql.dgs.internal.DgsSchemaProvider$createBasicDataFetcher$1.get(DgsSchemaProvider.kt:279)
    at com.netflix.graphql.dgs.metrics.micrometer.DgsGraphQLMetricsInstrumentation$instrumentDataFetcher$1.get(DgsGraphQLMetricsInstrumentation.kt:101)
    at graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation.lambda$instrumentDataFetcher$0(DataLoaderDispatcherInstrumentation.java:86)
    at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:270)
    ... 76 more
Caused by: org.springframework.orm.jpa.JpaSystemException: Unable to commit against JDBC Connection; nested exception is org.hibernate.TransactionException: Unable to commit against JDBC Connection
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:331)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
    at org.springframework.cloud.sleuth.instrument.tx.TracePlatformTransactionManager.commit(TracePlatformTransactionManager.java:121)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at org.springframework.integration.jdbc.lock.DefaultLockRepository$$EnhancerBySpringCGLIB$$29ab5ce4.acquire(<generated>)
    at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.doLock(JdbcLockRegistry.java:268)
    at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.tryLock(JdbcLockRegistry.java:249)
    ... 88 more
Caused by: org.hibernate.TransactionException: Unable to commit against JDBC Connection
            3 lines skipped for [org.hibernate]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
    ... 100 more
Caused by: org.postgresql.util.PSQLException: ERROR: could not serialize access due to read/write dependencies among transactions
  Detail: Reason code: Canceled on identification as a pivot, during commit attempt.
  Hint: The transaction might succeed if retried.
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2674)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2364)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:354)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:314)
    at org.postgresql.jdbc.PgConnection.executeTransactionCommand(PgConnection.java:853)
    at org.postgresql.jdbc.PgConnection.commit(PgConnection.java:875)
    at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:387)
    at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java)
            1 line skipped for [org.hibernate]

The transformation process should arrive to a CannotAcquireLockException, here, as the error is database serialization related.

I was searching for a way to extend the transform behavior on this line, but, cannot find a way to customize this transformation on the HibernateJpaDialect for that org.hibernate.TransactionException.

Note that I created an issue on Spring Integration and Hibernate, as I think Hibernate is the one who is not throwing the right context exception, however, I would like to be able to customize the behavior somehow in the Spring side.

Comment From: snicoll

@estigma88 unfortunately, if the exception is incorrect, there's nothing we can do about that. You can always override the dialect if you need custom exception handling.