I am new to Spring and trying to use Transactions. I am using spring-boot-starter-data-jpa
2.7.3. My code is like this:
@Transactional(rollbackFor = { SQLException.class }) // https://www.baeldung.com/transaction-configuration-with-jpa-and-spring
private void update(Bookings_V01 b) {
... some code here ...
Aggregates agg = aggregatesRepository.lockForUpdate(sav, pid, g);
... some code here ...
}
public interface AggregatesRepository extends CrudRepository<Aggregates, Integer> {
// https://www.baeldung.com/java-jpa-transaction-locks#:~:text=To%20specify%20a%20lock%20on,FROM%20Customer%20c%20WHERE%20c.
// When the lock is explicitly enabled and there is no active transaction, the
// underlying JPA implementation will throw a TransactionRequiredException.
// https://docs.oracle.com/javaee/7/api/javax/persistence/LockModeType.html
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@Query("select a from Aggregates a WHERE a.sav = :sav and a.pid = :pid and a.Period = :period")
Aggregates lockForUpdate(String sav, String pid, Period period);
}
When this code is run I see following message:
2022-09-14 17:39:13.248 TRACE 18401 --- [nio-8080-exec-1] o.s.t.i.TransactionInterceptor : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.lockForUpdate]: This method is not transactional.
and then this exception:
2022-09-14 17:39:13.285 ERROR 18401 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress] with root cause
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1644)
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617)
at org.hibernate.query.internal.AbstractProducedQuery.getSingleResult(AbstractProducedQuery.java:1665)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
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.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:406)
at jdk.proxy4/jdk.proxy4.$Proxy148.getSingleResult(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:198)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:156)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:144)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:160)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:145)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy4/jdk.proxy4.$Proxy129.lockForUpdate(Unknown Source)
at cdao.dpde.controllers.MainController.update(MainController.java:114)
How can I fix this? This link says
if we're using a Spring Boot project and have a spring-data-* or spring-tx dependencies on the classpath, then transaction management will be enabled by default.
as I am using spring-boot-starter-data-jpa
I have not done anything extra to enable transaction manager. below is dependency tree of spring-boot-starter-data-jpa
:
+- org.springframework.boot:spring-boot-starter-data-jpa:jar:2.7.3:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-aop:jar:2.7.3:compile
[INFO] | | +- org.springframework:spring-aop:jar:5.3.22:compile
[INFO] | | \- org.aspectj:aspectjweaver:jar:1.9.7:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-jdbc:jar:2.7.3:compile
[INFO] | | +- com.zaxxer:HikariCP:jar:4.0.3:compile
[INFO] | | \- org.springframework:spring-jdbc:jar:5.3.22:compile
[INFO] | +- jakarta.transaction:jakarta.transaction-api:jar:1.3.3:compile
[INFO] | +- jakarta.persistence:jakarta.persistence-api:jar:2.2.3:compile
[INFO] | +- org.hibernate:hibernate-core:jar:5.6.10.Final:compile
[INFO] | | +- org.jboss.logging:jboss-logging:jar:3.4.3.Final:compile
[INFO] | | +- net.bytebuddy:byte-buddy:jar:1.12.13:compile
[INFO] | | +- antlr:antlr:jar:2.7.7:compile
[INFO] | | +- org.jboss:jandex:jar:2.4.2.Final:compile
[INFO] | | +- com.fasterxml:classmate:jar:1.5.1:compile
[INFO] | | +- org.hibernate.common:hibernate-commons-annotations:jar:5.1.2.Final:compile
[INFO] | | \- org.glassfish.jaxb:jaxb-runtime:jar:2.3.6:compile
[INFO] | | +- org.glassfish.jaxb:txw2:jar:2.3.6:compile
[INFO] | | +- com.sun.istack:istack-commons-runtime:jar:3.0.12:compile
[INFO] | | \- com.sun.activation:jakarta.activation:jar:1.2.2:runtime
[INFO] | +- org.springframework.data:spring-data-jpa:jar:2.7.2:compile
[INFO] | | +- org.springframework.data:spring-data-commons:jar:2.7.2:compile
[INFO] | | +- org.springframework:spring-orm:jar:5.3.22:compile
[INFO] | | +- org.springframework:spring-context:jar:5.3.22:compile
[INFO] | | +- org.springframework:spring-tx:jar:5.3.22:compile
[INFO] | | \- org.springframework:spring-beans:jar:5.3.22:compile
[INFO] | \- org.springframework:spring-aspects:jar:5.3.22:compile