Spring事务传播机制

Spring事务传播行为验证



Spring事务传播机制

Spring中的Propagation枚举类中定义了七种事务传播机制,事务的传播机制都是针对被调用方来说的,假如,方法A中调用了B方法,对于方法B有以下七种事务传播机制来处理A的事务:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
}

验证需要的示例代码:

@RestController
@RequestMapping("/transactional")
public class TestTransactionalController {

    @Resource
    TestTransactionalAService transactionalAService;

    @RequestMapping("/fund")
    public String fund() throws ParseException {
        transactionalAService.subFund();
        return "OK";
    }
}

@Service
public class TestTransactionalAService {

    @Resource
    TestTransactionalADao transactionalADao;

    @Resource
    TestTransactionalBService transactionalBService;

    @Transactional
    public void subFund() throws ParseException {
        transactionalADao.subFund(1, 200, DateUtils.dateFormat(String.valueOf(System.currentTimeMillis()), false));
        transactionalBService.addFund();
    }
}

@Service
public class TestTransactionalBService {

    @Resource
    TestTransactionalBDao transactionalBDao;

    @Transactional
    public void addFund() throws ParseException {
        transactionalBDao.addFund(2, 200, DateUtils.dateFormat(String.valueOf(System.currentTimeMillis()), false));
    }
}

// 开启这三个类的debug日志即可,否则日志太多,不方便查看
logging.level.com.orkasgb.bigdatatools.dao.TestTransactionalADao=debug
logging.level.com.orkasgb.bigdatatools.dao.TestTransactionalBDao=debug
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=debug

REQUIRED:

事务机制的默认行为,如果调用者存在事务,则被调用者加入当前事务,如果不存在,则被调用者新建事务,即:A方法存在事务的时候,B方法就加入当前事务执行,否则,B方法新建一个事务执行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.REQUIRED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 11 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@641c8066]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@641c8066]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:24:53(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.REQUIRED)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为REQUIRED,所以加入了已经调用者创建的事务,以事务方式运行。
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:470)-Participating in existing transaction
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:24:53(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@641c8066]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@641c8066]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上的@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.REQUIRED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 11 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:35:44(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.REQUIRED)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为REQUIRED,所以自己执行时候创建了事务,以事务方式运行。
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalBService.addFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@10cb9808]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@10cb9808]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:35:44(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@10cb9808]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@10cb9808]]] after transaction

SUPPORTS:

如果调用者存在事务,则被调用者加入当前事务,如果不存在,则被调用者也不会新建事务,而是以非事务方式执行。即:A方法存在事务的时候,B方法就加入当前事务执行,否则,B方法不会新建一个事务,而是以非事务执行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.SUPPORTS)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 16 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@104ea18b]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@104ea18b]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:47:47(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.SUPPORTS)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为SUPPORTS,所以加入了调用者创建的事务,以事务方式运行。
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:470)-Participating in existing transaction
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:47:47(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@104ea18b]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@104ea18b]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.SUPPORTS)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 12 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:44:26(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.SUPPORTS)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为SUPPORTS,所以自己也没有创建事务,也以非事务方式运行。
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:44:27(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1

MANDATORY:

被调用者必须在事务中运行,如果调用者没有事务,被调用者将会抛出异常。即:A方法存在事务的时候,B方法就加入当前事务执行,否则,B方法直接抛出异常。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.MANDATORY)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 14 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@360fb7d5]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@360fb7d5]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:52:32(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.MANDATORY)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为MANDATORY,所以自己执行时候加入了调用者创建的事务中,以事务方式运行。
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:470)-Participating in existing transaction
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:52:32(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@360fb7d5]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@360fb7d5]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.MANDATORY)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 13 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:53:54(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.MANDATORY)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为MANDATORY,所以直接抛出异常,并且明确提示出 “ No existing transaction found ”
(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet].java:175)-Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'] with root cause
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:362)

REQUIRES_NEW:

被调用者必须在自己创建的事务中运行,如果调用者有事务,则被调用者将会将当前事务挂起,自己新建事务运行。即:A方法存在事务的时候,B方法就暂停当前事务并自己新建事务运行,否则,B方法直接创建事务运行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.REQUIRES_NEW)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 10 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@6b3810aa]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@6b3810aa]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:12:17(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.REQUIRES_NEW)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为REQUIRES_NEW,所以挂起了调用者创建的事务,并自己创建了新事务,以新的事务方式运行。
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:429)-Suspending current transaction, creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalBService.addFund]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@3c067a4f]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@3c067a4f]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:12:17(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@3c067a4f]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@3c067a4f]]] after transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:1008)-Resuming suspended transaction after completion of inner transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@6b3810aa]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@6b3810aa]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.REQUIRES_NEW)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 10 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:59:25(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.REQUIRES_NEW)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,,因为事务传播机制为REQUIRES_NEW,所以自己执行时候创建了新事务,以事务方式运行。    
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalBService.addFund]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@793d0dd7]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@793d0dd7]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 14:59:26(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@793d0dd7]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@793d0dd7]]] after transaction

NOT_SUPPORTED:

被调用者必须以非事务方式运行,如果调用者有事务,则被调用者将当前事务挂起,并以非事务方式运行,否则,就直接以普通方式运行。即:A方法存在事务的时候,B方法就暂停当前事务并以普通方式运行,否则,B方法直接以普通方式运行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NOT_SUPPORTED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 13 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1f421fc0]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1f421fc0]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:17:29(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NOT_SUPPORTED)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为NOT_SUPPORTED,所以挂起了调用者创建的事务,并以非事务方式运行。 
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:419)-Suspending current transaction
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:17:29(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:1008)-Resuming suspended transaction after completion of inner transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1f421fc0]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1f421fc0]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NOT_SUPPORTED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 10 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:20:11(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NOT_SUPPORTED)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为NOT_SUPPORTED,所以自己以非事务方式运行。 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:20:12(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1

NEVER:

被调用者必须以非事务方式运行,如果调用者有事务,则被调用者直接报错,否则以普通方式运行。即:A方法存在事务的时候,B方法直接报错,否则,B方法直接以普通方式运行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NEVER)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 10 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@5b918ce]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@5b918ce]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:25:09(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:833)-Initiating transaction rollback
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:341)-Rolling back JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@5b918ce]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@5b918ce]]] after transaction
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NEVER)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为NEVER,所以直接抛出异常,并且明确提示出 “ Existing transaction found ”    
(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet].java:175)-Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'] with root cause
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:413)

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NEVER)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 11 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:23:11(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NEVER)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为NEVER,所以自己以非事务方式运行。 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:23:11(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1

NESTED:

如果调用者有事务,则被调用者创建一个子事务嵌套在当前事务中运行,并跟随当前事务一起提交或者回滚,如果调用者没有事务,则被调用者创建一个新事务运行,此时和REQUIRED方式一致。即:A方法存在事务的时候,B方法创建一个子事务嵌套在当前事务中运行,并跟随当前事务一起提交或者回滚,否则,B方法直接创建一个新事务运行。

验证(开启debug日志,查看控制台日志):在TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NESTED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 10 ms
// 调用者TestTransactionalAService.subFund上增加了@Transactional注解,执行的时候创建了一个新的事务,所以TestTransactionalAService.subFund是以事务方式运行的   
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalAService.subFund]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1367561]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1367561]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:30:32(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NESTED)注解,执行的时候,发现调用者TestTransactionalAService.subFund已经创建了事务,因为事务传播机制为NESTED,所以自己创建了子事务,并以子事务方式运行。    
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:449)-Creating nested transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalBService.addFund]
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:30:32(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:733)-Releasing transaction savepoint
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1367561]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@1367561]]] after transaction

验证(开启debug日志,查看控制台日志):取消TestTransactionalAService.subFund上加上@Transactional注解,并在TestTransactionalBService.addFund上增加@Transactional(propagation = Propagation.NESTED)

(org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].java:173)-Initializing Spring DispatcherServlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:525)-Initializing Servlet 'dispatcherServlet'
(org.springframework.web.servlet.DispatcherServlet.java:547)-Completed initialization in 11 ms
// 调用者TestTransactionalAService.subFund上没有增加@Transactional注解,所以调用者TestTransactionalAService.subFund是以非事务方式运行的
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund - ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:33:54(String), 1(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalADao.subFund.java:143)-<==    Updates: 1
// 被调用者TestTransactionalBService.addFund上增加了@Transactional(propagation = Propagation.NESTED)注解,执行的时候,发现调用者TestTransactionalAService.subFund没有创建事务,因为事务传播机制为NESTED,所以自己创建了新的事务,并以事务方式运行。 
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:370)-Creating new transaction with name [com.orkasgb.bigdatatools.service.TestTransactionalBService.addFund]: PROPAGATION_NESTED,ISOLATION_DEFAULT
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:263)-Acquired Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@181e4cfe]]] for JDBC transaction
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:281)-Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@181e4cfe]]] to manual commit
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==>  Preparing: UPDATE orkasgb.t_oaksgb_account SET fund=fund + ?, `time`=? WHERE id=? 
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-==> Parameters: 200.0(Double), 2022-09-30 15:33:55(String), 2(Integer)
(com.orkasgb.bigdatatools.dao.TestTransactionalBDao.addFund.java:143)-<==    Updates: 1
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:740)-Initiating transaction commit
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:326)-Committing JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@181e4cfe]]]
(org.springframework.jdbc.datasource.DataSourceTransactionManager.java:385)-Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.cj.jdbc.ConnectionImpl@181e4cfe]]] after transaction
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜间沐水人

文章编写不易,一分钱也是爱。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值