Propagation.REQUIRES_NEW does not create a new transaction in Spring with JPA

I have the following scenario. I am using JPA, Spring:

@Autowired SampleService service; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void PerformLogic(LogicData data) throws SIASFaultMessage { SampleObject so = createSampleObject(); try{ .//do some logic to persist things in data . . persistData(data); . . . updateSampleObject(so); } catch(Exception){ updateSampleObject(so); throw new SIASFaultMessage(); } } @Transactional(propagation = Propagation.REQUIRES_NEW) public createSampleObject() { SampleObject so = new SampleObject(); . .//initialize so . service.persist(so); return so; } @Transactional(propagation = Propagation.REQUIRES_NEW) public updateSampleObject(SampleObject so) { service.persist(so); return so; } 

When everything works fine, the data is stored in the database without any problems. However, when an exception is thrown, I need the updateSampleObject (so) method to save the information in the database. This is not what is happening. If an exception is thrown, the updateSampleObject method also rolls back, which I don't need. I need these two methods ( createSampleObject and updateSampleObject ) to be persistently saved, regardless of whether an exception is thrown or not. How can I achieve this?

Also, if I exchange the createSampleObject and updateSampleObject methods with

 @Transactional(propagation = Propagation.NEVER) 

The idea is that an exception is thrown, and I get no exception. What is the problem? Analyzing the logs, I see this line:

 org.springframework.orm.jpa.JpaTransactionManager ==> Creating new transaction with name [com.test.PerformLogic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT.... 

which means that this transaction is created, but I do not see any hint of another transaction.

This is part of my configuration file for Spring regarding transactions.

 <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="packagesToScan" value="cu.jpa"/> <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">${hdm2ddl.auto}</prop> </props> </property> <property value="/META-INF/jpa-persistence.xml" name="persistenceXmlLocation"/> <property name="persistenceUnitName" value="jpaPersistenceUnit"/> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> <property name="nestedTransactionAllowed" value="true" /> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> 
+7
java spring hibernate jpa transactions
source share
2 answers

Spring transactions are proxy based. So, how does it work when bean A invokes the transaction bean B. Actually this is a link to the proxy server that delegates bean B. This proxy is the one that starts and completes / rolls back the transaction:

 A ---> proxy ---> B 

In your code, transactional method A calls another transactional method A. Thus, Spring cannot intercept the call and start a new transaction. This is a normal method call without a proxy.

So, if you want to start a new transaction, the createSampleObject() method must be in another bean introduced in your current bean.

This is explained in more detail in the documentation .

+25
source share

I assume that since both methods are in the same bean, AOP Spring is not able to intercept calls to the create / updateSampleObject method. Try moving the methods to a separate bean.

+4
source share

All Articles