Method with @Transactional commits the transaction when it returns. If you want to combine multiple transactional method in one transaction, propagation policy is the solution.
Solution A
- To make a parent method with @Transactional
- To delete @Transactional at sub methods to combine the transaction
Solution B
- To make a parent method with @Transactional (default propagation level is “MANDATORY”)
- To change sub method’s propagation level to “SUPPORTS” (which means “Support a current transaction, execute non-transactionally if none exists.”) or “MANDATORY” (which means “Support a current transaction, throw an exception if none exists.”)
- Be warned that the parent method accesses sub method through spring context (to access proxy object)
Example – parent method
@Repository public class TestMultiDao { @Autowired private TestSubDao subDao; @Transactional public void insertMulti() { subDao.insertData("1", "111"); subDao.insertData("2", "222"); } }
Example – sub method
@Repository public class TestSubDao { private JdbcTemplate jdbcTemplate; @Autowired public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } @Transactional(propagation=Propagation.SUPPORTS) public void insertData(String col1, String col2) { this.jdbcTemplate.update("INSERT INTO TRANSACTION_TEST(COL1, COL2) VALUES(?, ?)", col1, col2); } }
When running above code, the following log is shown
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Creating new transaction with name [test.dao.TestMultiDao.insertMulti]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ” DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Acquired Connection […] for JDBC transaction DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Switching JDBC Connection […] to manual commit DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Participating in existing transaction DEBUG: org.springframework.jdbc.core.JdbcTemplate – Executing prepared SQL update DEBUG: org.springframework.jdbc.core.JdbcTemplate – Executing prepared SQL statement [INSERT INTO TRANSACTION_TEST(COL1, COL2) VALUES(?, ?)] DEBUG: org.springframework.jdbc.core.JdbcTemplate – SQL update affected 1 rows DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Participating in existing transaction DEBUG: org.springframework.jdbc.core.JdbcTemplate – Executing prepared SQL update DEBUG: org.springframework.jdbc.core.JdbcTemplate – Executing prepared SQL statement [INSERT INTO TRANSACTION_TEST(COL1, COL2) VALUES(?, ?)] DEBUG: org.springframework.jdbc.core.JdbcTemplate – SQL update affected 1 rows DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Initiating transaction commit DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Committing JDBC transaction on Connection […] DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager – Releasing JDBC Connection […] after transaction DEBUG: org.springframework.jdbc.datasource.DataSourceUtils – Returning JDBC Connection to DataSource |
- A transaction object is created
- A jdbc connection is acquired and set as manual commit
- Executing the first sql with the connection
- Executing the second sql with the same connection
- Committing the transaction
- Releasing the connection