Spring事务传播机制详细讲解

文章目录

  • 一、事务传播机制
    • 1. REQUIRED:
    • 2. SUPPORTS:
    • 3. MANDATORY:
    • 4. REQUIRES_NEW:
    • 5. NOT_SUPPORTED:
    • 6. NEVER:
    • 7. NESTED:
  • 二、事务传播机制分类
    • 1. 支持当前事务的传播机制:REQUIRED、SUPPORTS、MANDATORY
    • 2. 不支持当前事务的传播机制:REQUIRES_NEW、NOT_SUPPORTED、NEVER
    • 3. 嵌套事务的传播机制:NESTED

Spring事务传播机制详细讲解_第1张图片

一、事务传播机制

1. REQUIRED:

如果当前存在事务,方法将在该事务中运行;否则,将创建一个新的事务。这是默认的传播行为。如果嵌套的方法出现异常,整个事务将回滚。

当使用REQUIRED传播机制时,如果当前已存在事务,则方法将在该事务中运行;如果当前没有事务,则将创建一个新的事务。

下面是一个简单的示例示范如何使用REQUIRED传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.REQUIRED)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用REQUIRED传播机制。如果在调用该方法时已经存在一个事务,那么该方法将在该事务中运行。如果在调用该方法时没有事务,那么将创建一个新的事务。

假设在调用performTransaction方法之前已经存在一个事务,那么在方法内部的数据库操作将在该事务中进行。如果任何一个数据库操作失败,事务将回滚,所有的改变将被撤销。

如果在调用performTransaction方法之前没有事务,那么将创建一个新的事务。在方法内部的数据库操作将在这个新的事务中进行。如果任何一个数据库操作失败,事务将回滚,所有的改变将被撤销。

这样做的好处是,如果在一个业务方法中调用多个数据库操作,可以确保这些操作要么全部成功,要么全部失败。如果其中一个操作失败,可以回滚整个事务,保持数据的一致性。

2. SUPPORTS:

有事物则加入事物,没有事物则普通执行

当使用SUPPORTS传播机制时,如果当前已存在事务,则方法将在该事务中运行;如果当前没有事务,则方法将在非事务环境中运行。

下面是一个简单的示例示范如何使用SUPPORTS传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用SUPPORTS传播机制。如果在调用该方法时已经存在一个事务,那么该方法将在该事务中运行。如果在调用该方法时没有事务,那么将在非事务环境中运行。

假设在调用performTransaction方法之前已经存在一个事务,那么在方法内部的数据库操作将在该事务中进行。如果任何一个数据库操作失败,事务将回滚,所有的改变将被撤销。

如果在调用performTransaction方法之前没有事务,那么将在非事务环境中执行方法内部的数据库操作。即使其中一个数据库操作失败,也不会回滚,因为非事务环境下没有事务可回滚。

这样做的好处是,可以在需要的时候使用事务,而在不需要事务的情况下,方法可以在非事务环境中运行,提高性能。但是需要注意的是,在非事务环境中执行的数据库操作将无法回滚,可能会导致数据不一致的问题,因此需要谨慎使用SUPPORTS传播机制。

3. MANDATORY:

方法必须在一个已存在的事务中运行,否则将抛出异常。它适用于需要强制事务支持的方法。

当使用MANDATORY传播机制时,方法必须在一个已存在的事务中执行。如果当前没有事务,则会抛出异常。

下面是一个简单的示例示范如何使用MANDATORY传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.MANDATORY)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用MANDATORY传播机制。如果在调用该方法时已经存在一个事务,那么该方法将在该事务中运行。如果在调用该方法时没有事务,那么将会抛出异常。

假设在调用performTransaction方法之前已经存在一个事务,那么在方法内部的数据库操作将在该事务中进行。如果任何一个数据库操作失败,事务将回滚,所有的改变将被撤销。

如果在调用performTransaction方法之前没有事务,那么将会抛出异常,因为MANDATORY传播机制要求方法必须在一个已存在的事务中执行。这样可以确保在调用该方法时,事务的一致性和完整性得到保证。

使用MANDATORY传播机制的好处是,可以确保方法在一个事务中执行,避免了在没有事务的情况下执行可能引起数据不一致的操作。这种传播机制通常用于业务操作中,确保相关操作在同一个事务中执行,保证数据的完整性。

4. REQUIRES_NEW:

每次执行时都会创建一个新的事务。

当使用REQUIRES_NEW传播机制时,方法将会在一个新的事务中执行。如果当前存在一个事务,则会挂起该事务,并在方法执行完毕后恢复原有事务。

下面是一个简单的示例示范如何使用REQUIRES_NEW传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用REQUIRES_NEW传播机制。无论当前是否存在一个事务,该方法都会在一个新的事务中执行。

假设在调用performTransaction方法之前已经存在一个事务,那么在方法内部的数据库操作将在一个新的事务中进行。如果任何一个数据库操作失败,新的事务将回滚,所有的改变将被撤销,但原有的事务不受影响。

如果在调用performTransaction方法之前没有事务,那么将会创建一个新的事务并在方法内部的数据库操作中使用。如果任何一个数据库操作失败,新的事务将回滚,所有的改变将被撤销。

使用REQUIRES_NEW传播机制的好处是,可以将方法的执行独立于当前的事务,确保方法在一个新的事务中执行。这种传播机制通常用于需要独立事务执行的情况,例如在进行一些敏感操作时,避免与现有事务发生冲突。同时,使用REQUIRES_NEW传播机制可以避免潜在的死锁问题,因为方法在一个新的事务中执行,不会与其他事务产生竞争。

5. NOT_SUPPORTED:

方法将以非事务的方式运行,如果当前存在事务,则将其挂起。适用于不需要事务支持的方法。
当使用NOT_SUPPORTED传播机制时,方法将会在非事务的上下文中执行。如果当前存在一个事务,则会将事务挂起,并在方法执行完毕后恢复原有事务。

下面是一个简单的示例示范如何使用NOT_SUPPORTED传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用NOT_SUPPORTED传播机制。无论当前是否存在一个事务,该方法都会在非事务的上下文中执行。

假设在调用performTransaction方法之前已经存在一个事务,那么在方法内部的数据库操作将在非事务的上下文中进行。如果任何一个数据库操作失败,将不会回滚,所有的改变将被提交。

如果在调用performTransaction方法之前没有事务,那么方法将在非事务的上下文中执行,同样,如果任何一个数据库操作失败,将不会回滚,所有的改变将被提交。

使用NOT_SUPPORTED传播机制的好处是,方法将在非事务的上下文中执行,不受当前事务的影响。这种传播机制通常用于不需要事务支持的操作,例如查询操作或不涉及数据更新的方法。同时,使用NOT_SUPPORTED传播机制可以避免潜在的事务相关问题,例如死锁或锁竞争。然而,需要注意的是,使用NOT_SUPPORTED传播机制会导致方法无法回滚,因此在处理异常情况时需要特别小心。

6. NEVER:

有事物则报异常,它适用于不允许事务支持的方法。

当使用NEVER传播机制时,方法将会在非事务的上下文中执行。如果当前存在一个事务,则会抛出一个异常,阻止方法执行。

下面是一个简单的示例示范如何使用NEVER传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.NEVER)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用NEVER传播机制。如果在调用该方法之前已经存在一个事务,那么方法将会抛出一个异常,阻止方法的执行。

使用NEVER传播机制的好处是,可以确保方法在非事务的上下文中执行,避免了方法对事务的依赖。这种传播机制通常用于强制要求方法不在事务中执行的情况,例如某个方法需要独立于当前事务执行,或者需要确保方法不会影响当前事务的状态。

需要注意的是,使用NEVER传播机制会抛出异常,因此在方法调用时需要处理该异常。同时,使用NEVER传播机制也意味着方法无法回滚,因此在处理异常情况时需要特别小心。

7. NESTED:

如果之前存在一个事务,则创建一个嵌套事务。嵌套事务的回滚不会影响到父事务,但是父事务的回滚会影响到嵌套事务。

当使用NESTED传播机制时,方法将在一个新的嵌套事务中执行。如果当前不存在事务,则会创建一个新的事务。如果当前存在事务,则会在当前事务的上下文中创建一个嵌套事务。

下面是一个简单的示例示范如何使用NESTED传播机制:

@Service
public class TransactionService {

    @Autowired
    private TransactionDao transactionDao;

    @Transactional(propagation = Propagation.NESTED)
    public void performTransaction(String fromAccount, String toAccount, double amount) {
        try {
            // 执行转账操作
            transactionDao.debit(fromAccount, amount);
            transactionDao.credit(toAccount, amount);
        } catch (Exception e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

在这个示例中,performTransaction方法使用NESTED传播机制。如果在调用该方法之前已经存在一个事务,那么方法将在当前事务的上下文中创建一个嵌套事务。如果在调用该方法之前不存在事务,则会创建一个新的事务。

NESTED传播机制的特点是,嵌套事务是作为当前事务的一部分进行管理的。当嵌套事务提交时,它会将自己的修改合并到父事务中;当嵌套事务回滚时,它会回滚自己的修改,而不会影响父事务的状态。如果父事务提交,嵌套事务的提交也会被提交;如果父事务回滚,嵌套事务的回滚也会被回滚。

需要注意的是,NESTED传播机制仅在特定的事务管理器中受支持,例如Spring的JtaTransactionManager。另外,嵌套事务的支持也取决于数据库的支持情况。

在使用NESTED传播机制时,需要考虑事务的管理和回滚策略。由于嵌套事务是作为当前事务的一部分进行管理的,因此在处理异常情况时需要特别小心,以确保事务的正确回滚。

总结
事务传播机制允许开发者根据实际需求来控制事务的行为。通过合理选择事务传播机制,可以保证事务的一致性和可靠性,提高系统的稳定性和性能。

需要注意的是,事务传播机制只对方法级别的事务起作用,对注解方式的事务不适用。在使用注解方式时,可以通过@Transactional注解的propagation属性来指定事务的传播行为。

二、事务传播机制分类

1. 支持当前事务的传播机制:REQUIRED、SUPPORTS、MANDATORY

  • REQUIRED:如果当前存在事务,方法将在该事务中运行;否则,将创建一个新的事务。
  • SUPPORTS:如果当前存在事务,方法将在该事务中运行;否则,以非事务的方式执行。
  • MANDATORY:方法必须在一个已存在的事务中运行,否则将抛出异常。

2. 不支持当前事务的传播机制:REQUIRES_NEW、NOT_SUPPORTED、NEVER

  • REQUIRES_NEW:方法将创建一个新的事务,并在自己的事务中运行,如果当前存在事务,则将其挂起。
  • NOT_SUPPORTED:方法将以非事务的方式运行,如果当前存在事务,则将其挂起。
  • NEVER:方法不能在一个已存在的事务中运行,否则将抛出异常。

3. 嵌套事务的传播机制:NESTED

  • NESTED:如果当前存在事务,则在嵌套事务中执行;如果没有事务,则行为类似于REQUIRED。嵌套事务是外部事务的一部分,可以独立地进行提交或回滚。
    这些传播机制可以根据业务需求来选择,确保事务的隔离性和一致性。

你可能感兴趣的:(《Java基础》专栏,spring)