jakarta.persistence.TransactionRequiredException on @Query, @Modifying and @Transactional methods

We have migrated the spring boot application from 2.7.x to 3.2.1 version. It progressively took to upgrade of Java11 to 17 and Hibernate version from 5.6.x to 6.4.1.

Before migration we were using spring.jpa.properties.hibernate.allow_update_outside_transaction=true property in application.properties file to avoid below error when we try to execute the delete query with both @Transactional and @Modifying annotation and it was working fine.

AllPageDaoShouldTest.cleanupIntegrationTest:228 ▒ InvalidDataAccessApiUsage no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress.

But after spring boot migration from 2.7.x to 3.2.1 version i.e from Hibernate 5.6.x to 6.4.1 version hibernate.allow_update_outside_transaction=true hibernate property is not working to allow the update outside the transaction boundary and we are facing below error

Can you please let us know similar property which we need to use after hibernate migration from 5.6x to 6.4.1 to have the similar behavior like to allow update outside transaction boundary. Thanks in advance.

Caused by: jakarta.persistence.TransactionRequiredException: Query requires transaction be in progress, but no transaction is known to be in progress
        at org.hibernate.internal.AbstractSharedSessionContract.prepareForQueryExecution(AbstractSharedSessionContract.java:419) ~[hibernate-core-6.1.6.Final.jar!/:6.1.6.Final]
        at org.hibernate.query.sqm.internal.QuerySqmImpl.doExecuteUpdate(QuerySqmImpl.java:727) ~[hibernate-core-6.1.6.Final.jar!/:6.1.6.Final]
        at org.hibernate.query.sqm.internal.QuerySqmImpl.executeUpdate(QuerySqmImpl.java:698) ~[hibernate-core-6.1.6.Final.jar!/:6.1.6.Final]
        at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:236) ~[spring-data-jpa-3.0.1.jar!/:3.0.1]
        at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90) ~[spring-data-jpa-3.0.1.jar!/:3.0.1]
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:148) ~[spring-data-jpa-3.0.1.jar!/:3.0.1]
        at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:136) ~[spring-data-jpa-3.0.1.jar!/:3.0.1]
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136) ~[spring-data-commons-3.0.1.jar!/:3.0.1]
        at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120) ~[spring-data-commons-3.0.1.jar!/:3.0.1]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164) ~[spring-data-commons-3.0.1.jar!/:3.0.1]
        at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) ~[spring-data-commons-3.0.1.jar!/:3.0.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:77) ~[spring-data-commons-3.0.1.jar!/:3.0.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-6.0.4.jar!/:6.0.4]
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-6.0.4.jar!/:6.0.4]
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:134) ~[spring-data-jpa-3.0.1.jar!/:3.0.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:218) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at jdk.proxy2.$Proxy227.deleteSiteByName(Unknown Source) ~[?:?]
        at com.nokia.smp.serviceportal.service.DefaultSiteService.deleteSiteByName(DefaultSiteService.java:121) ~[ServicePortalCommon-240.0.0.6-SNAPSHOT.jar!/:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:699) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at com.nokia.smp.serviceportal.service.DefaultSiteService$$SpringCGLIB$$0.deleteSiteByName(<generated>) ~[ServicePortalCommon-240.0.0.6-SNAPSHOT.jar!/:?]
        at com.nokia.smp.serviceportal.rest.SiteDefinitionRestController.deleteSiteByName(SiteDefinitionRestController.java:204) ~[ServicePortalRestResources-240.0.0.6-SNAPSHOT.jar!/:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor.invoke(AuthorizationManagerBeforeMethodInterceptor.java:199) ~[spring-security-core-6.0.1.jar!/:6.0.1]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) ~[spring-aop-6.0.4.jar!/:6.0.4]
        at com.nokia.smp.serviceportal.rest.SiteDefinitionRestController$$SpringCGLIB$$0.deleteSiteByName(<generated>) ~[ServicePortalRestResources-240.0.0.6-SNAPSHOT.jar!/:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
        at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-6.0.12.jar!/:6.0.12]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1081) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:974) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1011) ~[spring-webmvc-6.0.12.jar!/:6.0.12]
        ... 135 more
2024-02-09 11:50:29.636 ERROR [XNIO-1 task-4] io

Also debugged the code and spring is passing the correct vendor properties to hibernate but hibernate is not taking this hibernate.allow_update_outside_transaction=true property into effect.

Please Note: This property was perfectly working fine in Hibernate 5.6.x i.e before migration from 5.6.x to 6.4.1.

Please help with this issue.

Thanks

This is a bug. The call to getSession().prepareForQueryExecution( true ); in org.hibernate.query.sqm.internal.QuerySqmImpl#doExecuteUpdate is wrong and should be removed. Please try to create a reproducer with our test case template and if you are able to reproduce the issue, create a bug ticket in our issue tracker and attach that reproducer.

Thank you for the reply.

Can you please let us know in which version this bug will be fixed?

Hibernate ORM is open source, which means you can not only see the source code, but also contribute back. So if something is important to you, you can work on it yourself and provide a PR so that it gets integrated upstream.
If you’re unable or unwilling to work on this yourself, you can also contract someone else to fix HHH-17743 on your behalf, e.g. Red Hat.
Or you simply wait until someone finds the time and interest to fix this for you.

Hi @beikov ,

I have raised a PR for this HHH-17743 Allow updates outside transaction by subijayb · Pull Request #7867 · hibernate/hibernate-orm (github.com)

Can someone from your team please review it?

1 Like