Spring Boot中的事务管理:保证数据的一致性和可靠性

举报
bug菌 发表于 2023/10/11 17:02:55 2023/10/11
【摘要】 🏆本文收录于《Spring Boot从入门到精通》,专门攻坚指数提升,2023 年国内最系统+最强(更新中)。


🏆本文收录于《Spring Boot从入门到精通》,专门攻坚指数提升,2023 年国内最系统+最强(更新中)。

本专栏致力打造最硬核Spring Boot 系列教程,从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。

环境说明:Windows10 + Idea2021.3.2 + Jdk1.8 + SpringBoot 2.3.1.RELEASE

前言

在Web应用程序中处理多个数据库操作时,可能会遇到数据不一致的问题。为了解决这个问题,Java中有一个叫做事务的机制。Spring Boot为我们提供了一种方便和简单的方式来实现事务的管理。

在本文中,我们将学习如何在Spring Boot应用程序中使用事务,以确保数据一致性。

摘要

在本文中,我们将学习以下内容:

  1. 什么是事务?
  2. Spring Boot中的事务管理
  3. 事务管理的四种传播行为
  4. 事务管理的三种隔离级别
  5. 如何在Spring Boot应用程序中使用事务
  6. 如何在Spring Boot应用程序中测试事务

正文

什么是事务?

事务是指一系列操作,这些操作要么全部成功,要么全部失败。事务的目的是确保数据一致性。如果在事务中执行一个操作失败,则该事务必须被回滚。这意味着,所有在该事务中执行的操作都必须撤销。

Spring Boot中的事务管理

Spring Boot为我们提供了一个方便的机制来管理事务。在Spring Boot中,我们可以使用注解来声明一个方法是一个事务。

事务管理的四种传播行为

在Spring Boot中,我们可以使用传播行为定义事务处理方法的行为。Spring Boot提供了以下四种传播行为:

  1. REQUIRED:如果一个方法在另一个方法中被调用,那么它将在当前事务中运行。如果当前没有活动的事务,则它将创建一个新事务。
  2. REQUIRES_NEW:如果一个方法在另一个方法中被调用,那么它将在新事务中运行。如果当前有一个活动的事务,则它将被挂起。
  3. SUPPORTS:如果一个方法在另一个方法中被调用,那么它将在当前事务中运行。如果当前没有活动的事务,则它将以非事务方式运行。
  4. NOT_SUPPORTED:如果一个方法在另一个方法中被调用,那么它将以非事务方式运行。如果当前有一个活动的事务,则它将被挂起。

事务管理的三种隔离级别

在Spring Boot中,我们可以使用隔离级别定义事务的隔离级别。Spring Boot提供了以下三种隔离级别:

  1. DEFAULT:使用默认的隔离级别。
  2. READ_COMMITTED:该隔离级别允许读取已提交的数据。其他事务已经提交的数据将被读取。
  3. READ_UNCOMMITTED:该隔离级别允许读取未提交的数据。其他事务未提交的数据也可以被读取。

如何在Spring Boot应用程序中使用事务

在Spring Boot应用程序中使用事务非常简单。我们只需要在要执行事务的方法上加上一个@Transactional注解即可。例如,以下是一个使用事务的示例:

@Transactional
public void transferMoney(Account from, Account to, BigDecimal amount) {
    if (from.getBalance().compareTo(amount) < 0) {
        throw new InsufficientFundsException("Insufficient funds in account " + from.getId());
    }
    from.setBalance(from.getBalance().subtract(amount));
    to.setBalance(to.getBalance().add(amount));
    accountRepository.save(from);
    accountRepository.save(to);
}

在上面的示例中,我们使用@Transactional注解将transferMoney方法标记为一个事务方法。如果在方法执行期间发生异常,则事务将回滚。否则,事务将提交。

如何在Spring Boot应用程序中测试事务

在Spring Boot应用程序中测试事务非常容易。我们只需要在测试类上添加以下注解:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MyServiceTest {

    @Autowired
    private MyService myService;

    // ...

}

在上面的示例中,我们使用了@Transactional注解来标记测试类,这将确保测试方法在执行后自动回滚事务。这样,我们就可以在测试过程中执行事务并确保数据一致性。

代码演示

以下是使用Spring Boot的一个简单示例,其中演示了如何使用事务。

Account.java

@Entity
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    private BigDecimal balance;

    // getters and setters

}

AccountRepository.java

@Repository
public interface AccountRepository extends CrudRepository<Account, Long> {

}

AccountService.java

@Service
public class AccountService {

    private final AccountRepository accountRepository;

    public AccountService(AccountRepository accountRepository) {
        this.accountRepository = accountRepository;
    }

    @Transactional
    public void transferMoney(Account from, Account to, BigDecimal amount) {
        if (from.getBalance().compareTo(amount) < 0) {
            throw new InsufficientFundsException("Insufficient funds in account " + from.getId());
        }
        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));
        accountRepository.save(from);
        accountRepository.save(to);
    }

}

AccountController.java

@RestController
@RequestMapping("/accounts")
public class AccountController {

    private final AccountService accountService;

    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }

    @PostMapping("/transfer")
    public void transferMoney(
            @RequestParam Long fromId,
            @RequestParam Long toId,
            @RequestParam BigDecimal amount) {

        Account from = accountService.getAccountById(fromId);
        Account to = accountService.getAccountById(toId);

        accountService.transferMoney(from, to, amount);

    }

}

AccountControllerTest.java

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class AccountControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private AccountService accountService;

    @Test
    public void testTransferMoney() throws Exception {
        Account from = new Account();
        from.setName("from");
        from.setBalance(new BigDecimal("100.00"));
        accountService.saveAccount(from);

        Account to = new Account();
        to.setName("to");
        to.setBalance(new BigDecimal("100.00"));
        accountService.saveAccount(to);

        mockMvc.perform(post("/accounts/transfer")
                .param("fromId", from.getId().toString())
                .param("toId", to.getId().toString())
                .param("amount", "50.00"))
                .andExpect(status().isOk());

        from = accountService.getAccountById(from.getId());
        to = accountService.getAccountById(to.getId());

        assertThat(from.getBalance()).isEqualTo(new BigDecimal("50.00"));
        assertThat(to.getBalance()).isEqualTo(new BigDecimal("150.00"));
    }

}

附录源码

  如上涉及所有源码均已上传同步在「GitHub」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

小结

在本文中,我们学习了在Spring Boot应用程序中使用事务的方法。我们了解了事务的概念,以及Spring Boot提供的事务管理机制。我们学习了事务的四种传播行为和三种隔离级别,并且了解了如何在Spring Boot应用程序中使用事务。最后,我们还介绍了如何在Spring Boot应用程序中测试事务。

希望这篇文章对你有所帮助!

总结

事务是确保数据一致性的重要机制,而Spring Boot提供了一种简单方便的事务管理机制。在开发应用程序时,我们应该充分利用Spring Boot的事务管理机制来确保数据一致性。在编写测试用例时,我们也应该使用@Transactional注解和其他相关的注解来测试我们的事务是否正常工作。

附录源码

  如上涉及所有源码均已上传同步在「GitHub」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你


无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学Spring Boot」,从入门到精通,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

📣关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计15w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。