Spring Boot 揭秘与实战(二) 数据存储篇 - 声明式事务管理
本文讲解 Spring Boot 如何使用声明式事务管理。
声明式事务
Spring 支持声明式事务,使用 @Transactional 注解在方法上表明这个方法需要事务支持。此时,Spring 拦截器会在这个方法调用时,开启一个新的事务,当方法运行结束且无异常的情况下,提交这个事务。
Spring 提供一个 @EnableTransactionManagement 注解在配置类上来开启声明式事务的支持。使用了 @EnableTransactionManagement 后,Spring 会自动扫描注解 @Transactional 的方法和类。
Spring Boot默认集成事务
Spring Boot 默认集成事务,所以无须手动开启使用 @EnableTransactionManagement 注解,就可以用 @Transactional注解进行事务管理。我们如果使用到 spring-boot-starter-jdbc 或 spring-boot-starter-data-jpa,Spring Boot 会自动默认分别注入
DataSourceTransactionManager 或 JpaTransactionManager。
实战演练
我们在前文「Spring Boot 揭秘与实战(二) 数据存储篇 - MySQL」的案例上,进行实战演练。
实体对象
我们先创建一个实体对象。为了便于测试,我们对外提供一个构造方法。
- public class Author {
- private Long id;
- private String realName;
- private String nickName;
- public Author() {}
- public Author(String realName, String nickName) {
- this.realName = realName;
- this.nickName = nickName;
- }
- // SET和GET方法
- }
DAO 相关
这里,为了测试事务,我们只提供一个方法新增方法。
- @Repository("transactional.authorDao")
- public class AuthorDao {
- @Autowired
- private JdbcTemplate jdbcTemplate;
- public int add(Author author) {
- return jdbcTemplate.update("insert into t_author(real_name, nick_name) values(?, ?)",
- author.getRealName(), author.getNickName());
- }
- }
Service 相关
我们提供三个方法。通过定义 Author 的 realName 字段长度必须小于等于 5,如果字段长度超过规定长度就会触发参数异常。
值得注意的是,noRollbackFor 修饰表明不做事务回滚,rollbackFor 修饰的表明需要事务回滚。
- @Service("transactional.authorService")
- public class AuthorService {
- @Autowired
- private AuthorDao authorDao;
- public int add1(Author author) {
- int n = this.authorDao.add(author);
- if(author.getRealName().length() > 5){
- throw new IllegalArgumentException("author real name is too long.");
- }
- return n;
- }
- @Transactional(noRollbackFor={IllegalArgumentException.class})
- public int add2(Author author) {
- int n = this.authorDao.add(author);
- if(author.getRealName().length() > 5){
- throw new IllegalArgumentException("author real name is too long.");
- }
- return n;
- }
- @Transactional(rollbackFor={IllegalArgumentException.class})
- public int add3(Author author) {
- int n = this.authorDao.add(author);
- if(author.getRealName().length() > 5){
- throw new IllegalArgumentException("author real name is too long.");
- }
- return n;
- }
- }
测试,测试
- @RunWith(SpringJUnit4ClassRunner.class)
- @SpringApplicationConfiguration(WebMain.class)
- public class TransactionalTest {
- @Autowired
- protected AuthorService authorService;
- //@Test
- public void add1() throws Exception {
- authorService.add1(new Author("梁桂钊", "梁桂钊"));
- authorService.add1(new Author("LiangGzone", "LiangGzone"));
- }
- //@Test
- public void add2() throws Exception {
- authorService.add2(new Author("梁桂钊", "梁桂钊"));
- authorService.add2(new Author("LiangGzone", "LiangGzone"));
- }
- @Test
- public void add3() throws Exception {
- authorService.add3(new Author("梁桂钊", "梁桂钊"));
- authorService.add3(new Author("LiangGzone", "LiangGzone"));
- }
- }
我们分别对上面的三个方法进行测试,只有最后一个方法进行了事务回滚。
源代码
相关示例完整代码: springboot-action
(完)

【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期