天天看点

Spring中的事务管理:概念、技术和最佳实践

作者:爱科学的卫斯理
Spring中的事务管理:概念、技术和最佳实践

Spring事务

介绍

事务管理在处理复杂的业务操作中起着至关重要的作用。 在处理多个数据库操作时,确保这些事务的原子性、一致性、隔离性和持久性(ACID:atomicity、consistency、isolation和durability)至关重要。 在本文中,我们将深入探讨Spring中的事务管理,介绍其概念、技术和最佳实践。

理解事务管理

事务管理是指协调构组成单个业务操作的多个任务。 本质上,这是“全有或全无”原则——如果事务的任何部分失败,则整个事务失败,数据库状态保持不变。

Spring的事务管理功能以其灵活性和易于配置着称。让我们深入研究它是如何工作的。

Spring的事务管理

Spring为跨不同的事务API提供了一致编程模型。 它为低级的事务管理提供了一个抽象层,允许你只需要编写代码而无需担心底层事务系统。

我们用下面简单的代码片段来演示:

import org.springframework.transaction.annotation.Transactional;

@Service
public class UserServiceImpl implements UserService {
   
    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void createUsers(User user1, User user2) {
        userRepository.save(user1);
        userRepository.save(user2);
    }
}           

@Transactional 注解标记需要在事务上下文中执行的方法。 如果在此方法中抛出任何RuntimeException ,Spring将自动回滚事务; 否则,它将在方法执行完成后提交事务。

Spring事务管理技术

Spring提供两种方式来管理事务:

  • 编程式事务管理:这种方式提供了极大的灵活性,但代码很难维护。 它会涉及到使用TransactionTemplate 或PlatformTransactionManager 接口的启动、提交或回滚事务的代码。
  • 声明式事务管理:这种方式使用AOP(面向切面编程),它将事务管理代码与业务逻辑分开。 它更简单,也是我们首选的方法。 它使用@Transactional 注解,如我们上面的代码所演示的。

最佳实践

下面是Spring事务管理的一些最佳实践:

Best Practices

  1. 合理的隔离界别:设置合适的隔离级别,避免脏读、幻读、不可重复读等问题。 隔离级别定义了一个事务中的更改如何对其他事务可见。
  2. 合适的事务传播:事务传播是指事务如何相互关联。 Spring支持七种类型的事务传播,包括REQUIRED 、SUPPORTS 和NEVER 等。
  3. 事务超时:指定事务超时以防止事务无限期地运行。 这在资源有限的生产环境中可能至关重要。
  4. 只读事务:对于只读数据的事务,可以设置为只读。 这有助于Spring执行一些优化并提高整体性能。
  5. 最小化事务范围:使事务中的代码尽可能简洁。 事务中的代码越长,锁定时间越长,这会影响应用程序的性能和可扩展性。
  6. 为特定异常回滚事务:默认情况下,Spring会回滚运行时未检查异常(unchecked exceptions)的事务。 对于已检查的异常(checked exceptions),它会提交事务。 如果你需要回滚某些特定的已检查异常,你可以在@Transactional 注释中指定它们。
@Transactional(rollbackFor=IOException.class)
public void applyMethod() throws IOException {
    //...
}           

处理多个事务

在某些情况下,我们必须在相同或不同的数据库中处理多个事务。 Spring通过其管理分布式事务的能力来支持这一点。 在管理多个事务时,必须了解两阶段提交(Two-Phase Commit)协议。 两阶段提交协议是一种分布式算法,协调所有参与分布式原子事务的进程是提交还是中止。

Spring使用JtaTransactionManager 来管理分布式事务。 它使用Java Transaction API (JTA),它支持跨多个事务资源的分布式事务。

@Bean
public JtaTransactionManager jtaTransactionManager() {
    JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
    jtaTransactionManager.setTransactionManager(someTransactionManager());
    jtaTransactionManager.setUserTransaction(someUserTransaction());
    return jtaTransactionManager;
}           

JtaTransactionManager 被配置为一个Spring的Bean。 它需要对Java EE环境中的UserTransaction 和TransactionManager 进行引用。

处理事务失败

事务管理的另一个关键方面是处理事务失败。 Spring的TransactionTemplate 提供了一种简单的方法来执行数据库操作和处理可能导致事务失败的异常。

import org.springframework.transaction.support.TransactionTemplate;

@Service
public class UserServiceImpl implements UserService {
   
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TransactionTemplate transactionTemplate;

    public void createUsers(User user1, User user2) {
        transactionTemplate.execute(status -> {
            try {
                userRepository.save(user1);
                userRepository.save(user2);
            } catch (DataAccessException e) {
                status.setRollbackOnly();
                throw e;
            }
            return null;
        });
    }
}           

在这段代码中,transactionTemplate.execute() 启动一个新的事务,如果没有异常发生则提交它。 如果抛出异常,它会将事务标记为回滚。

总结

无论你应用程序的范围或复杂性如何,Spring 的事务管理为处理复杂的数据库事务提供了一个无缝、可靠的解决方案。

其一致的编程模型有助于便利使用不同的事务API,其强大的功能集允许分布式事务、高效的故障处理和性能优化。

通过遵循本文概述的最佳实践,并明智地使用Spring的事务管理功能,你可以创建健壮、可扩展且高效的应用程序。 了解你的特定业务需求和潜在权衡以选择最佳策略来管理Spring 应用程序中的事务是至关重要的。

原文地址:https://medium.com/@AlexanderObregon/transactional-management-in-spring-concepts-techniques-and-best-practices-c3d76ef64165

继续阅读