Spring 编程常见错误 50 例
傅健
Cisco 高级软件工程师、Netty 源码贡献者
17065 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 29 讲
结束语 (1讲)
期末测试 (1讲)
Spring 编程常见错误 50 例
15
15
1.0x
00:00/00:00
登录|注册

20 | Spring 事务常见错误(下)

你好,我是傅健。
通过上一节课的学习,我们了解了 Spring 事务的原理,并解决了几个常见的问题。这节课我们将继续讨论事务中的另外两个问题,一个是关于事务的传播机制,另一个是关于多数据源的切换问题,通过这两个问题,你可以更加深入地了解 Spring 事务的核心机制。

案例 1:嵌套事务回滚错误

上一节课我们完成了学生注册功能,假设我们需要对这个功能继续进行扩展,当学生注册完成后,需要给这个学生登记一门英语必修课,并更新这门课的登记学生数。为此,我添加了两个表。
课程表 course,记录课程名称和注册的学生数。
CREATE TABLE `course` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_name` varchar(64) DEFAULT NULL,
`number` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
学生选课表 student_course,记录学生表 student 和课程表 course 之间的多对多关联。
CREATE TABLE `student_course` (
`student_id` int(11) NOT NULL,
`course_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
同时我为课程表初始化了一条课程信息,id = 1,course_name = "英语",number = 0。
接下来我们完成用户的相关操作,主要包括两部分。
新增学生选课记录
@Mapper
public interface StudentCourseMapper {
@Insert("INSERT INTO `student_course`(`student_id`, `course_id`) VALUES (#{studentId}, #{courseId})")
void saveStudentCourse(@Param("studentId") Integer studentId, @Param("courseId") Integer courseId);
}
课程登记学生数 + 1
@Mapper
public interface CourseMapper {
@Update("update `course` set number = number + 1 where id = #{id}")
void addCourseNumber(int courseId);
}
我们增加了一个新的业务类 CourseService,用于实现相关业务逻辑。分别调用了上述两个方法来保存学生与课程的关联关系,并给课程注册人数 +1。最后,别忘了给这个方法加上事务注解。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了Spring事务中的常见错误和解决方法,重点讨论了事务的传播机制和多数据源切换问题。通过案例展示了嵌套事务回滚错误的情况,并详细分析了Spring事务处理的核心机制,包括事务的创建、提交和异常处理流程。通过对Spring源码的解析,揭示了内外层事务共用一个事务导致的回滚问题。文章还介绍了如何修改传播属性以解决全局回滚问题,以及如何实现在一个事务中同时操作多个数据源的功能。另外,文章还介绍了如何使用Spring AOP和自定义注解来实现数据库切换。总的来说,本文适合对Spring事务感兴趣的技术人员阅读,有助于加深对Spring事务处理机制的理解,提高对事务处理错误的识别和解决能力。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Spring 编程常见错误 50 例》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • Wallace Pang
    spring boot多数据源更简单
    2021-06-23
    4
  • Yarin
    内外部事务都使用注解,希望两者同步回滚。但是内部事务抛出特定异常回滚,外部事务接收到的是回滚异常,如何把这个异常传给外部事务呢?我们目前做的是内部事务手动开启事务,在抛出指定异常后手动回滚,再往外抛出指定异常。欢迎交流,有没有更好的方法。
    2023-02-25归属地:北京
    2
  • ly
    第1个案例个人觉得有个小问题: 内层事务是给学员存储要学的学科,如果用的新事务require_new,那么假设内层事务程序改为不抛异常了,内层事务就会正常先入库。 而此时外层事务还未提交,一旦出现程序问题,导致异常,那么学员就不能保存成功,但是结果呢,学员所学的学科已经成功入库了。感觉就产生垃圾数据了。 我不知道分析对没
    2022-04-15
    2
    2
  • 杨宇
    对于高频访问数据库的场景,DriverManagerDatasource效率低下,应改用HikariDatasource
    2021-12-30
    2
  • 干货满满
    2021-06-18
    1
  • study的程序员
    直接指定两个TransactionManager ,两个DataSource ,@Transactional指定manager 更方便吧
    2022-11-22归属地:上海
  • study的程序员
    point.proceed(); MyDataSource.clearDataSource(); 要加上try finally
    2022-11-22归属地:上海
  • 陌兮
    虽然多数据源事务的操作让人眼前一亮,但是涉及到的问题也非常多。感觉实用性并不大啊
    2022-10-09归属地:广东
  • palladio
    不行。每个事务都是和对应数据源绑定的,在默认事务声明的情况下,外层和内层的事务是同一个,也就意味着两个事务绑定的数据源是同一个。所以外层和内层事务回滚的都是同一个数据源,card 库回滚不了
    2022-04-01
  • S | c
    案例二没太理解,多个数据源的场景为什么不声明多个transactionManager bean实例?各管各的dataSource。。。 @Transactional可以指定对应的transactionManager bean吧,反正你内部的发卡service也是在card库上开一个新事务来跑。
    2022-03-09
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部