详解spring: 事务属性的设置

本文深入探讨了事务隔离属性和传播属性的概念,包括脏读、不可重复读、幻读、第一类和第二类更新丢失等问题,以及Spring中事务隔离级别的实现。同时,介绍了事务的传播属性,包括REQUIRES_NEW、NESTED等行为,并通过实例展示了如何在Spring中配置事务。此外,文章还概述了事务的特性、Spring事务与Hibernate事务、JTA、数据库事务之间的关系,以及如何在Java中使用注解进行事务配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

隔离属性

主要是保证并发条件下事务对数据读取和更新安全性。

并发过程中事务可能出现的问题:

1) 脏读:一个事务读取到了另一个事务还没有提交的数据。

2) 不可重复读:一个事务两次读取同一个资源,读到的结果不同。具体原因是中间另一个事物修改了资源。

3) 幻象读:事务在进行表级运算(例如sum,max…)中间有insert或delete对象,这段是我的理解,一般资料写是insert。

4) 第一类更新丢失(回滚丢失):两个事务都对同一个资源先后做了更新,但是先更新的事务回滚了。造成后更新的时候更新操作失败。即回滚造成的更新丢失

5) 第二类更新丢失(覆盖丢失):和不可重复读类似,两个事务同事读取一个资源进行更新,但是没有同步,造成后提交的事务覆盖了先提交事务做的更新。即覆盖造成的更新丢失。

 

   Spring的事务隔离级别:

1) DEFAULT 使用数据库中设置的隔离级别 ( 默认 ) , DBA默认的设置来决定隔离级别 .

2)READ_UNCOMMITTED 未提交读,没有隔离机制,会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )

3)READ_COMMITTED 提交读,保证当前事务读取到的资源是已经被修改提交的。一个事务能读取到别的事务提交的更新数据,不能看到未提交的更新数据,不可能可能出现丢失更新、脏读,但可能出现不可重复读、幻读;

4)REPEATABLE_READ 可重复读,保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响,可能可能出现丢失更新、脏读、不可重复读,但可能出现幻读;

5) SERIALIZABLE序列化,最高隔离级别,不允许事务并发执行,而必须串行化执行,最安全,不可能出现更新、脏读、不可重复读、幻读。实质是锁表。

 



 

传播属性

主要是定义方法是否以事务方式运行还有嵌套情况下如何执行。目前看事务的属性以注解方式设置最好最方便。

关于propagation属性的7个传播行为 REQUIRED SUPPORTS NOT_SUPPORTED REQUIRES_NEW NESTED 抛异常的两个 MANDATORY NEVER

最常用的两个
required 优先以事务方式执行
supports 优先以非事务方式执行

NOT_SUPPORTED 以非事务方式执行

抛异常的两个 
MANDATORY 当前必须已经存在一个事务,否则报错。如果存在则放在一起执行。
NEVER     必须以非事务方式执行,必须当前没有事务执行,否则报错

涉及嵌套的两个
REQUIRES_NEW 无论有没有被嵌套或者已经存在一个事务,都新建一个事务,在新事务中单独执行,外层事务或已经存在的事务先挂起。也就是说这个新的事务作为单独的一个原子。
NESTED 如果被嵌套,就在嵌套事务中执行,如果没有被嵌套,则按照required的方式执行

理解REQUIRES_NEW 和NOT_SUPPORTED,这两种其实都是限定当前事务已经存在事务隔离,互不影响。已经存在的事务作为两个事务来运行的。比如:一个单号发生器的方法可以设置为REQUIRES_NEW方法,保证并发下的单例模式,外部方法获取单号以后,内部设置数据库的单号自增1。这个即便旧的事务出现问题回滚,新的事务也是不需要回滚的

下面两段是否正确还需要验证:

PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA 事务管理器的支持。

使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。

 

要了解事务之间的关系,如果是嵌套事务关系,需要考虑父子关系。判断当前事务是否是被嵌套的。

深层需要考虑分布式和各种场景下事务的关系:分布式事务 嵌套事务 多层事务

Spring中事务的配置方法:

XML方式的配置

Spring中的事务配置方式是按照AOP,在类中设置切入点,引入事务处理策略。然后通过代理模式,定义事务处理策略。

<tx:advice id="txAdvice" transaction-manager="txManager">
	<tx:attributes>
		<!--以事务的方式执行 匹配所有以save开头的方法 propagation事务传播属性-->
		<tx:method name="save*" propagation="REQUIRED" />
		<tx:method name="add*" propagation="REQUIRED" />
		<tx:method name="create*" propagation="REQUIRED" />
		<tx:method name="insert*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="merge*" propagation="REQUIRED" />
		<tx:method name="del*" propagation="REQUIRED" />
		<tx:method name="remove*" propagation="REQUIRED" />
		<tx:method name="put*" propagation="REQUIRED" />
		<!--以非事务的方式执行-->
		<tx:method name="get*" propagation="NOT_SUPPORTED" read-only="true" />
		<tx:method name="count*" propagation="NOT_SUPPORTED" read-only="true" />
		<tx:method name="find*" propagation="NOT_SUPPORTED" read-only="true" />
		<tx:method name="list*" propagation="NOT_SUPPORTED" read-only="true" />
		<tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />
		<!--rollback-for配置触发回滚的异常 -->
		<!--isolation事务隔离级别,默认为“DEFAULT” no-rollback-for配置不被触发回滚的异常-->
		<tx:method name="doComplexLogic" propagation="NESTED"  
		isolation="REPEATABLE_READ" timeout="1000" rollback-for="java.lang.Exception"  
		no-rollback-for="com.mysrc.service.CustomRuntimeException" />  
		</tx:attributes>
</tx:advice>
<aop:config>
	<!--切入点 表达式的意思是拦截cn包及子包下的chapter9. service包及子包下的任何类的任何方法-->
	<aop:pointcut id="txPointcut" expression="execution(* cn.javass..service.*.*(..))" />
	<!--表示切入点txPointcut 使用的事务规则是txAdvice -->
	<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>


java注解方式配置:

package com.baobaotao.service;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class ForumService {
    private UserService userService;
    @Transactional(propagation=Propagation.NEVER)
    public void addTopic(){
    	//add Topic
		userService.addCredits();
    }
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
}


事务的特性 
ACID 
原子性 一个事务中的所有事务作为一个整体即一个原子,如果执行失败要回滚则一起回滚。
一致性 在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
隔离性 不同的同类事务事务之间相互隔离,类似于不同的线程,不会相互影响。
持久性 事务执行的结果会持久化到存储介质。


事务常问问题

事务有哪几个特性?

原子性 一致性 隔离性 持久性

 

Spring事务,Hibernate事务,JTA,数据库事务,他们之间的有什么关系?

1 一般底层的一个事务对应一个jdbc的connection session连接。

2事务通俗的理解,事务是一组原子操作的一个单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简答的说就是:要么全部执行成功,要么全部撤销不执行

3 JTA是一个协议和接口定义api,支持分布式的同事访问多个多种连接。Hibernate实现了这个协议和接口。

JTA的例子https://www.ibm.com/developerworks/cn/java/j-lo-jta/

4

Hibernate的缓存详解

http://www.cnblogs.com/hnlshzx/p/3497545.html

 

参考:

http://sishuok.com/forum/blogPost/list/2508.html

图书 Spring 3.x 企业应用开发实战



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值