Spring
声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的
try
…
catch
…
finally
代码。
我们在使用
Spring
声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。
Spring
在
TransactionDefinition
接口中定义这些属性
,
以供
PlatfromTransactionManager
使用
, PlatfromTransactionManager
是
spring
事务管理的核心接口。
<!-- [if !supportLists]-->l
<!-- [endif]-->getTimeout()
方法,它返回事务必须在多少秒内完成。
<!-- [if !supportLists]-->l
<!-- [endif]-->isReadOnly()
,
事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的。
<!-- [if !supportLists]-->l
<!-- [endif]-->getIsolationLevel()
方法返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。
在
TransactionDefinition
接口中定义了五个不同的事务隔离级别:
<!-- [if !supportLists]-->l
<!-- [endif]-->ISOLATION_DEFAULT
这是一个
PlatfromTransactionManager
默认的隔离级别,使用数据库默认的事务隔离级别
.
另外四个与
JDBC
的隔离级别相对象
<!-- [if !supportLists]-->l
<!-- [endif]-->ISOLATION_READ_UNCOMMITTED
这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
例如
: Mary
的原工资为
1000,
财务人员将
Mary
的工资改为了
8000
,但未提交事务
与此同时,
Mary
正在读取自己的工资
Mary
发现自己的工资变为了
8000
,欢天喜地!
而财务发现操作有误,而回滚了事务
,Mary
的工资又变为了
1000.
像这样
,Mary
记取的工资数
8000
是一个脏数据。
<!-- [if !supportLists]-->l
<!-- [endif]-->ISOLATION_READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
<!-- [if !supportLists]-->l
<!-- [endif]-->ISOLATION_REPEATABLE_READ
这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生
(
不可重复读
)
。
在事务
1
中,
Mary
读取了自己的工资为
1000,
操作并没有完成
在事务
2
中,这时财务人员修改了
Mary
的工资为
2000,
并提交了事务
.
在事务
1
中,
Mary
再次读取自己的工资时,工资变为了
2000
在一个事务中前后两次读取的结果并不致,导致了不可重复读。
使用
ISOLATION_REPEATABLE_READ
可以避免这种情况发生。
<!-- [if !supportLists]-->l
<!-- [endif]-->ISOLATION_SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
目前工资为
1000
的员工有
10
人。
事务
1,
读取所有工资为
1000
的员工。
共读取
10
条记录
这时另一个事务向
employee
表插入了一条员工记录,工资也为
1000
事务
1
再次读取所有工资为
1000
的员工
共读取到了
11
条记录,这就产生了幻像读。
ISOLATION_SERIALIZABLE
能避免这样的情况发生。但是这样也耗费了最大的资源。
getPropagationBehavior
()
返回事务的传播行为,由是否有一个活动的事务来决定一个事务调用。
在
TransactionDefinition
接口中定义了七个事务传播行为:
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_REQUIRED
如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
使用
spring
声明式事务,
spring
使用
AOP
来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。
单独调用
methodB
方法
相当于
Spring
保证在
methodB
方法中所有的调用都获得到一个相同的连接。在调用
methodB
时,没有一个存在的事务,所以获得一个新的连接,开启了一个新的事务。
单独调用
MethodA
时,在
MethodA
内又会调用
MethodB.
执行效果相当于
调用
MethodA
时,环境中没有事务,所以开启一个新的事务
.
当在
MethodA
中调用
MethodB
时,环境中已经有了一个事务,所以
methodB
就加入当前事务。
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_SUPPORTS
如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,
PROPAGATION_SUPPORTS
与不使用事务有少许不同。
单纯的调用
methodB
时,
methodB
方法是非事务的执行的。
当调用
methdA
时
,methodB
则加入了
methodA
的事务中
,
事务地执行。
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_MANDATORY
如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
当单独调用
methodB
时,因为当前没有一个活动的事务,则会抛出异常
throw new
IllegalTransactionStateException("Transaction propagation ''mandatory''
but no existing transaction found");
当调用
methodA
时,
methodB
则加入到
methodA
的事务中,事务地执行。
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_REQUIRES_NEW
总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
当单独调用
methodB
时,相当于把
methodb
声明为
REQUIRED
。开启一个新的事务,事务地执行。
当调用
methodA
时
情况有些大不一样
.
相当于下面的效果。
在这里,我把
ts1
称为外层事务,
ts2
称为内层事务。从上面的代码可以看出,
ts2
与
ts1
是两个独立的事务,互不相干。
Ts2
是否成功并不依赖于
ts1
。如果
methodA
方法在调用
methodB
方法后的
doSomeThingB
方法失败了,而
methodB
方法所做的结果依然被提交。而除了
methodB
之外的其它代码导致的结果却被回滚了。
使用
PROPAGATION_REQUIRES_NEW,
需要使用
JtaTransactionManager
作为事务管理器。
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_NOT_SUPPORTED
总是非事务地执行,并挂起任何存在的事务。
当单独调用
methodB
时,不启用任何事务机制,非事务地执行。
当调用
methodA
时,相当于下面的效果
使用
PROPAGATION_NOT_SUPPORTED,
也需要使用
JtaTransactionManager
作为事务管理器。
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_NEVER
总是非事务地执行,如果存在一个活动事务,则抛出异常
单独调用
methodB
,则非事务的执行。
调用
methodA
则会抛出异常
<!-- [if !supportLists]-->l
<!-- [endif]-->PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中
.
如果没有活动事务
,
则按
TransactionDefinition.PROPAGATION_REQUIRED
属性执行
这是一个嵌套事务
,
使用
JDBC 3.0
驱动时
,
仅仅支持
DataSourceTransactionManager
作为事务管理器。需要
JDBC
驱动的
java.sql.Savepoint
类。有一些
JTA
的事务管理器实现可能也提供了同样的功能。
使用
PROPAGATION_NESTED
,还需要把
PlatformTransactionManager
的
nestedTransactionAllowed
属性设为
true;
而
nestedTransactionAllowed
属性值默认为
false;
如果单独调用
methodB
方法,则按
REQUIRED
属性执行。
如果调用
methodA
方法,相当于下面的效果
当
methodB
方法调用之前,调用
setSavepoint
方法,保存当前的状态到
savepoint
。如果
methodB
方法调用失败,则恢复到之前保存的状态。但是需要注意的是,这时的事务并没有进行提交,如果后续的代码
(doSomeThingB()
方法
)
调用失败,则回滚包括
methodB
方法的所有操作。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
PROPAGATION_NESTED
与
PROPAGATION_REQUIRES_NEW
的区别:
它们非常类似
,
都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。使用
PROPAGATION_REQUIRES_NEW
时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务这是一个真正的嵌套事务。同时它需要
JTA
事务管理器的支持。
使用
PROPAGATION_NESTED
时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。
DataSourceTransactionManager
使用
savepoint
支持
PROPAGATION_NESTED
时,需要
JDBC 3.0
以上驱动及
1.4
以上的
JDK
版本支持。其它的
JTA TrasactionManager
实现可能有不同的支持方式。
PROPAGATION_REQUIRED
应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。
分享到:
相关推荐
Spring事务管理的目的是确保数据的一致性和完整性,尤其是在多操作、多资源的环境中。本Demo将深入探讨Spring如何实现事务的管理。 首先,Spring提供了两种主要的事务管理方式:编程式事务管理和声明式事务管理。 ...
本资源包提供了进行Spring事务管理开发所需的所有关键库,包括框架基础、核心组件、AOP(面向切面编程)支持、日志处理、编译工具以及与数据库交互的相关jar包。下面将对这些知识点进行详细解释: 1. **Spring框架*...
Spring 框架是Java开发中...理解并熟练掌握Spring事务管理,对于提升应用程序的稳定性和可靠性至关重要。在实际开发中,结合声明式事务管理、事务传播行为、隔离级别和回滚规则,可以有效地确保数据的完整性和一致性。
Spring事务管理.pdf 1.资料 2.本地事务与分布式事务 3.编程式模型 4.宣告式模型
Synchronized锁在Spring事务管理下,导致线程不安全。
本篇将深入探讨Spring事务管理的核心概念、工作原理以及如何使用`spring-tx-3.2.0.RELEASE.jar`这个jar包。 首先,我们需要理解什么是事务。在数据库系统中,事务是一组操作,这些操作被视为一个整体,要么全部完成...
标题“Spring事务管理失效原因汇总”指出了本文的核心内容是分析在使用Spring框架进行事务管理时可能遇到的问题及其原因。描述部分进一步说明了事务失效的后果往往不明显,容易在测试环节被忽略,但在生产环境中出现...
本篇文章将深入探讨Spring事务管理的五种方法,旨在帮助开发者更好地理解和运用这一核心特性。 首先,我们来了解什么是事务。在数据库操作中,事务是一组逻辑操作,这些操作要么全部成功,要么全部失败,确保数据的...
本文将详细介绍Spring事务管理的四种方式:编程式事务管理、声明式事务管理、PlatformTransactionManager接口以及TransactionTemplate。 1. **编程式事务管理**:这是一种手动控制事务的方式,通过在代码中调用`...
### Spring事务管理详解 #### 一、Spring事务管理的重要性及必要性 在现代软件开发中,事务管理是一项至关重要的技术,特别是在涉及数据库操作时。事务能够确保一系列操作要么全部成功,要么全部失败,这对于保持...
Spring事务管理是Spring框架的核心特性之一,它提供了一种强大且灵活的方式来管理应用程序中的事务边界。在企业级Java应用中,事务处理是确保数据一致性、完整性和可靠性的关键部分。本篇文章将深入探讨Spring的事务...
总的来说,Spring事务管理提供了一种灵活、强大的方式来处理应用程序中的事务,无论是在简单还是复杂的事务场景下,都能有效保证数据的一致性和完整性。通过声明式事务管理,开发者可以将关注点从事务细节中解脱出来...
Spring事务管理是Spring框架的核心特性之一,它提供了一种在Java应用中管理和协调数据库事务的标准方式。对于有Java基础的开发者来说,理解并掌握Spring事务管理至关重要,因为这有助于确保数据的一致性和完整性,...
当出现像描述中那样的问题——SQL语句执行出错但事务未回滚时,我们需要深入理解Spring事务管理的配置和机制。以下是一些关键知识点: 1. **Spring事务管理类型**: - **编程式事务管理**:通过`...
spring事务管理几种方式代码实例:涉及编程式事务,声明式事务之拦截器代理方式、AOP切面通知方式、AspectJ注解方式,通过不同方式实例代码展现,总结spring事务管理的一般规律,从宏观上加深理解spring事务管理特性...
在思维导图"Spring Transaction.twd"中,可能包含了Spring事务管理的各个概念和它们之间的关系,如事务的ACID属性(原子性、一致性、隔离性和持久性),事务管理器,以及声明式和编程式事务管理的实现方式。...
### Spring事务管理的方法 #### 一、引言 在企业级应用开发中,事务管理是一项至关重要的技术。Spring框架作为Java领域中一个非常流行的轻量级框架,为开发者提供了多种方式来实现事务管理,其中主要分为编程式...