前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring @Transactional工作原理

Spring @Transactional工作原理

作者头像
哲洛不闹
发布于 2018-09-19 03:32:02
发布于 2018-09-19 03:32:02
2.4K0
举报
文章被收录于专栏:java一日一条java一日一条

本文将深入研究Spring的事务管理。主要介绍@Transactional在底层是如何工作的。

JPA和事务管理

很重要的一点是JPA本身并不提供任何类型的声明式事务管理。如果在依赖注入容器之外使用JPA,事务处理必须由开发人员编程实现。

这种方式的事务管理使事务范围可以在代码中很清晰地表达出来,但它有以下缺点:

  • 容易出现重复代码和错误
  • 任何错误可能产生较大的影响
  • 错误难以调试和复现
  • 降低了代码库的可读性
  • 如果该方法调用了其他的事务方法如何处理呢?

使用Spring @Transactional

使用Spring @Transactional,上面的代码就简化为:

代码更加简洁,可读性更好,也是目前Spring中事务处理的推荐方式。

通过使用@Transactional,事务传播等很多重要方面可以自动处理。这种情况下如果businessLogic()调用了其他事务方法,该方法将根据选项确定如何加入正在运行事务。

这个强大机制的一个潜在缺点是它隐藏了底层的运行,当它不能正常工作时很难调试。

@Transactional含义

关于@Transactional,关键点之一是要考虑两个独立的概念,它们都有各自的范围和生命周期:

  • persistence context(持久化上下文)
  • database transaction(事务)

@Transactional本身定义了单个事务的范围。这个事务在persistence context的范围内。

JPA中的持久化上下文是EntityManager,内部实现使用了Hibernate Session(使用Hibernate作为持久化provider)。

持久化上下文仅仅是一个同步对象,它记录了有限集合的Java对象的状态,并且保证这些对象的变化最终持久化到数据库

这是与单个事务非常不同的概念。一个Entity Manager可以跨越多个事务使用,而且的确是这样使用的。

EntityManager何时跨越多个事务?

最常见的情况是应用使用Open Session In View模式处理懒初始化异常时,之前的文章介绍过这种做法的优势和劣势。

这种情况下视图层运行的多个查询处于独立的事务中,而不是单事务的业务逻辑,但这些查询由相同的entity manager管理。

另一种情况是开发人员将持久化上下文标记为PersistenceContextType.EXTENDED,这表示它能够响应多个请求。

如何定义EntityManager和Transaction之间的关系?

这由应用开发者来选择,但是JPA Entity Manager最常用的方式是“Entity Manager per application transaction”(每个事务都有自己的实体管理器)模式。entity manager注入的常用方法是:

这里默认为“Entity Manager per transaction”模式。这种模式下如果在@Transactional方法内部使用该Entity Manager,那么该方法将在单一事务中运行。

@PersistenceContext如何工作?

随之而来的问题就是@PersistenceContext如何仅在容器启动时注入entity manager,假定entity manager生命周期很短暂,而且每次请求需要多个entity manager。

答案是它不能:EntityManager是一个接口,注入到spring bean中的不是entity manager本身,而是在运行时代理具体entity manager的context aware proxy(上下文感知代理)

通常用于代理的具体类为SharedEntityManagerInvocationHandler,借助调试器可以确认这一点。

那么@Transactional如何工作?

实现了EntityManager接口的持久化上下文代理并不是声明式事务管理的唯一部分,事实上包含三个组成部分:

  • EntityManager Proxy本身
  • 事务的切面
  • 事务管理器

看一下这三部分以及它们之间的相互作用。

事务的切面

事务的切面是一个“around(环绕)”切面,在注解的业务方法前后都可以被调用。实现切面的具体类是TransactionInterceptor

事务的切面有两个主要职责:

  • 在’before’时,切面提供一个调用点,来决定被调用业务方法应该在正在进行事务的范围内运行,还是开始一个新的独立事务。
  • 在’after’时,切面需要确定事务被提交,回滚或者继续运行。

在’before’时,事务切面自身不包含任何决策逻辑,是否开始新事务的决策委派给事务管理器完成。

事务管理器

事务管理器需要解决下面两个问题:

  • 新的Entity Manager是否应该被创建?
  • 是否应该开始新的事务?

这些需要事务切面’before’逻辑被调用时决定。事务管理器的决策基于以下两点:

  • 事务是否正在进行
  • 事务方法的propagation属性(比如REQUIRES_NEW总要开始新事务)

如果事务管理器确定要创建新事务,那么将:

  • 创建一个新的entity manager
  • entity manager绑定到当前线程
  • 数据库连接池中获取连接
  • 将连接绑定到当前线程

使用ThreadLocal变量将entity manager和数据库连接都绑定到当前线程。

事务运行时他们存储在线程中,当它们不再被使用时,事务管理器决定是否将他们清除。

程序的任何部分如果需要当前的entity manager和数据库连接都可以从线程中获取。

EntityManager proxy

EntityManager proxy(前面已经介绍过)就是谜题的最后一部分。当业务方法调用entityManager.persist()时,这不是由entity manager直接调用的。

而是业务方法调用代理,代理从线程获取当前的entity manager,前面介绍过事务管理器将entity manager绑定到线程。

了解了@Transactional机制的各个部分,我们来看一下实现它的常用Spring配置。

整合三个部分

如何将三个部分组合起来使事务注解可以正确地发挥作用呢?首先定义entity manager工厂。

这样就可以通过持久化上下文注解注入Entity Manager proxy。

下一步实现配置事务管理器和在@Transactional注解的类中应用事务的切面。

注解@EnableTransactionManagement通知Spring,@Transactional注解的类被事务的切面包围。这样@Transactional就可以使用了。

总结

Spring声明式事务管理机制非常强大,但它可能被误用或者容易发生配置错误。

当这个机制不能正常工作或者未达到预期运行结果等问题出现时,理解它的内部工作情况是很有帮助的。

需要记住的最重要的一点是,要考虑到两个概念:事务和持久化上下文,每个都有自己不可读的明显的生命周期。

原文链接: javacodegeeks 翻译: ImportNew.com - hejiani

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2015-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java一日一条 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring声明式事务、编程式事务一文打尽
关于数据库事务、锁可以先行查看此文:MySQL数据库读写锁示例详解、事务隔离级别示例详解。
青山师
2023/05/05
1.2K0
Spring声明式事务、编程式事务一文打尽
flea-db使用之JPA分库分表实现
flea-frame-db使用之基于EntityManager实现JPA分表的数据库操作【旧】
huazie
2024/10/24
3420
flea-db使用之JPA分库分表实现
猫头鹰的深夜翻译:spring事务管理
Spring Framework提供了两种编程式事务管理方法。 a. 使用TransactionTemplate (Spring推荐这种实现): Context Xml file:
眯眯眼的猫头鹰
2018/10/31
6210
Spring 面试题,打包给大家
AOP:Aspect Oriented Program, 面向(方面)切面的编程;Filter(过滤器)也是一种 AOP. AOP 是一种新的 方法论, 是对传统 OOP(Object-OrientedProgramming, 面向对象编程) 的补充. AOP 的主要编程对象是切面(aspect),而切面模块化横切关注点.可以举例通过事务说明.
cxuan
2020/11/23
3600
Spring 面试题,打包给大家
Spring 事务管理详解
我们知道,在JavaEE的开发过程中,service方法用于处理主要的业务逻辑,而业务逻辑的处理往往伴随着对数据库的多个操作。以我们生活中常见的转账为例,service方法要实现将A账户转账到B账户的功能,则该方法内必定要有两个操作:先将A账户的金额减去要转账的数目,然后将B账户加上相应的金额数目。这两个操作必定要全部成功,方才表示本次转账成功;若有任何一方失败,则另一方必须回滚(即全部失败)。事务指的就是这样一组操作:这组操作是不可分割的,要么全部成功,要么全部失败
凯哥Java
2022/12/16
4630
Spring 事务管理详解
spring中@transactional注解的作用(spring 事务实现原理)
事物管理对于企业应用来说是至关重要的,好使出现异常情况,它也可以保证数据的一致性。
全栈程序员站长
2022/07/30
8450
一文带你看懂Spring事务!
Spring事务管理我相信大家都用得很多,但可能仅仅局限于一个@Transactional注解或者在XML中配置事务相关的东西。不管怎么说,日常可能足够我们去用了。但作为程序员,无论是为了面试还是说更好把控自己写的代码,还是应该得多多了解一下Spring事务的一些细节。
Java3y
2019/03/07
4580
一文带你看懂Spring事务!
深入了解 Spring boot的事务管理机制:掌握 Spring 事务的几种传播行为、隔离级别和回滚机制,理解 AOP 在事务管理中的应用
在应用程序中,事务管理是确保数据的一致性和完整性的重要组成部分。Spring 事务管理提供了一种可靠且灵活的方式来管理事务,确保在数据库操作过程中的原子性、一致性、隔离性和持久性。
苏泽
2024/03/16
2.6K0
深入了解 Spring boot的事务管理机制:掌握 Spring 事务的几种传播行为、隔离级别和回滚机制,理解 AOP 在事务管理中的应用
深入理解Spring框架中的声明式事务管理
事务管理是数据库操作中的关键环节,确保数据的一致性和完整性。在复杂的业务逻辑中,事务管理能保证操作的原子性,即要么全部成功,要么全部失败。
windealli
2024/06/25
3980
深入理解Spring框架中的声明式事务管理
Spring事务的传播机制及底层原理解析
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是最常见的选择,大部分业务场景都适用。
用户7353950
2024/05/20
7250
Spring事务的传播机制及底层原理解析
spring 常见9个相关面试问题
IOC:控制反转,原来我们使用的时候对象是由使用者控制的,有了spring之后,可以将整个对象交给容器来帮我们进行管理(理论思想)
知识浅谈
2022/05/19
3060
spring 常见9个相关面试问题
Spring源码剖析8:Spring事务概述
事务首先是一系列操作组成的工作单元,该工作单元内的操作是不可分割的,即要么所有操作都做,要么所有操作都不做,这就是事务。
Java技术江湖
2019/11/26
5960
Spring连接池与事务管理 | Spring学习笔记
第一步:导入 jar 包:c3p0-version*.jar 和 mchange-commons-java-version*.jar
做棵大树
2022/09/27
4230
Spring的@Transactional如何实现的(必考)
@Transactional是spring中声明式事务管理的注解配置方式,相信这个注解的作用大家都很清楚。@Transactional注解可以帮助我们把事务开启、提交或者回滚的操作,通过aop的方式进行管理。
肉眼品世界
2021/10/27
3.8K0
深入理解JPA
Java Persistence API(JPA)是Java平台上的一套ORM(对象关系映射)规范,它为Java应用提供了与数据库交互的标准方式。JPA的设计目标是简化开发者对数据库的访问,提高持久化层的灵活性和可维护性。本文将深入介绍JPA的基本概念以及在Java应用中的应用场景。
GeekLiHua
2025/01/21
2000
Spring学习(2)——AOP部分
在OOP的开发中,对于一些重复的操作可以抽离成模块,这可以减少代码量,但还是无法从根本上解决代码的冗余。在这种情况下我们可以把这些重复的操作抽离成切面,通过在运行时动态代理组合进原有的对象,这就是AOP,它是对OOP的补充。
玛卡bug卡
2022/09/20
2670
spring 事务机制的个人总结
Spring的事务机制虽然已经有非常多的资料介绍了,但是实际使用的时候还是常常栽坑里,相信这是大部分程序员的使用感受或者曾经的使用感受,所以这篇文章将会做一个完整的总结,用理论结合实际的代码实战的方式来弄懂Spring事务的机制到底应该如何使用以及内部是如何进行设计的。
阿东
2022/01/20
1.1K0
spring 事务机制的个人总结
Spring 是如何保证一个事务内获取同一个Connection
Spring有声明式事务和编程式事务,声明式事务只需要提供 @Transactional的注解。然后事务的开启、提交、回滚、资源的清理都由Spring 来管理,开发人员只需要关心业务即可。
王小明_HIT
2020/02/17
2K0
Spring全家桶之SpringData——Spring 整合Hibernate与Hibernate Jpa
注意 1. sql语句 ,是通过对象查询的表 ,虽然可以出现select 但是却不能出现通配符 *,故可以省略 Select * 2 .区别 getCurrentSession 与openSession 方法的用法 getCurrentSession:当前session 必须要有事务边界, 且只能处理唯一的一个事务。当事务提交或者回滚后session 自动失效 openSession:每次都会打开一个新的session.加入每次使用多次。则获得的是不同session 对象。使用完毕后我们需要手动的调用colse方法关闭session
时间静止不是简史
2020/07/25
3.1K0
Spring-事务
事务的4个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durabilily)。
lpe234
2021/03/02
5170
相关推荐
Spring声明式事务、编程式事务一文打尽
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档