Spring中事务管理

1.什么是事务?

事务是逻辑上的一组操作,这组操作要么全部成功,要么全部失败

2.事务具有四大特性ACID

1)原子性(Atomicity):即不可分割性,事务要么全部被执行,要么就全部不被执行。如果事务的所有子事务全部提交成功,则所有的数据库操作被提交,数据库状态发生转换;如果有子事务失败,则其他子事务的数据库操作被回滚,即数据库回到事务执行前的状态会发生状态转换

2)一致性(Consistency)事务的执行使得数据库从一种正确状态转换成另一种正确状态。例如对于银行转账事务,不管事务成功还是失败,应该保证事务结束后两个转账账户的存款总额是与转账前一致的。

3)隔离性(Isolation)并发执行的事务隔离的,一个不影响一个,每个事务都有各自的完整数据空间。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。通过设置数据库的 隔离级别 ,可以达到不同的隔离效果。

4)持久性(Durability):当提交了事务之后,对数据库中的数据进行的操作持久生效,不会无缘无故的回滚.

事务并发】,如果没有采取必要的隔离机制,会引起那些并发问题?

↑ 多个事务同时运行                (丢失更新、脏读、不可重复读、幻读

假设张三办了一张 银行卡,余额100元

第一类丢失更新:两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。

脏读:一个事务读取另外一个事务还没有提交的数据

不可重复读(虚读):针对修改   一个事务对同一行数据重复读取两次,但是却得到了不同的结果。

第二类丢失更新一个事务覆盖另一个事务已提交的数据   一个事务的更新覆盖了另一个事务的更新。更新丢失本质上是写操作的冲突,解决办法是一个一个地写。

幻读:针对增加删除  一个事务两次读取一个范围的记录,两次读取的记录数不一致

幻象读本质上是读写操作的冲突,解决办法是读完再写。

不可重复读和幻读的区别:

1)不可重复读 的重点是修改:

同样的条件, 你读取过的数据, 再次读取出来发现值不一样了

2)幻读 的重点在于新增或者删除

同样的条件, 第1次和第2次读出来的记录数不一样

解决并发问题的途径是什么?答案是:采取有效的隔离机制。怎样实现事务的隔离呢?隔离机制的实现必须使用锁

 

当数据库系统采用Read Committed隔离级别时(优先考虑,它能够避免脏读,而且具有较好的并发性能。,会导致不可重复读第二类丢失更新的并发问题。可以在应用程序中采用悲观锁乐观锁来避免这类问题:

数据库系统提供了四种事务隔离级别供用户选择:

①Read Uncommitted (读取未提交)防止第一类丢失更新,对应整数1

②Read Committed(读取已提交)防止脏读,对应整数2

③Repeatable Read(可重复读)防止不可重复读及第二类丢失更新,不可以预防幻读,对应整数4

④Serializable(串行话)隔离级别最高,但是并发性能最差,对应整数8

隔离级别越来越严格,数据安全和真实性越来越高,但并发性能越来越低。

1)乐观锁(Optimistic Lock):顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁是在更新会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。为了维护正确的数据,乐观锁使用应用程序上的版本控制(由程序逻辑来实现的)来避免可能出现的并发问题。

Read Committed + 乐观锁 -> Repeatable Read

①在实体类中加入存储版本的字段version,类型可以为short/int/long,并添加setter/getter方法

private int version;(在set 方法里面 更改修饰符 为private)

②在映射文件中紧跟id标签,加入<version>标签

<version name="version" column="version"></version>

效果: 更改一次 version 由0变1  不更改 提交 无效果

2)悲观锁(Pessimistic Lock):顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁这样别人想拿这个数据就会block直到它拿到锁。为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它影响并发性能,因此应该很谨慎使用悲观锁。

使用方法:

Dept dept = (Dept)session.load(Dept.class, 1l, LockOptions.UPGRADE);

利用数据库中的独占锁来完成:例如:select * from employee for update;

在Hibernate中,使用悲观锁来控制并发,其本质就是利用数据库中的独占锁

(两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。)

3.Spring中事务的管理

Spring中主要提供了以下3个接口来对事务进行管理

PlatformTransactionManager 平台事务管理器

这个接口下包含以下实现类

DataSourceTransactionManager、HibernateTransactionManager、JdoTransactionManager、JpaTransactionManager等

其中常用:

I:DataSourceTransactionManager 用来管理jdbc事务以及MyBatis/iBatis事务

II:HibernateTransactionManager 用来管理Hibernate事务

TransactionDefinition 事务定义:定义一些事务的信息(包括事务的隔离级别、传播行为、超时、只读)

隔离级别:针对并发选择合适的隔离级别

ISOLATION_DEFAULT:使用数据库默认隔离级别,mysql默认为REPEATABLE_READ,oracle默认为READ_COMMITTED

传播行为

***PROPAGATION_REQUIRED:支持当前事务,如果没有,就新建一个

PROPAGATION_SUPPORTS:支持当前事务,如果没有,就不使用事务

PROPAGATION_MANDATORY:支持当前事务,如果没有,抛出异常

----------------------

**PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务

PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务,挂起当前事务

PROPAGATION_NEVER:以非事务方式运行,如果有事务,抛出异常

-----------------------

*PROPAGATION_NESTED:嵌套事务,例如a方法调用b方法,可以在某个位置设置一个保存点,如果b中出现异常需要回滚事务,可以选择回滚到保存点或者初始位置

其它

TIMEOUT_DEFAULT:设置超时时间

TransactionStatus 事务的具体运行状态

hasSavepoint():判断是否有保存点

isCompleted():判断是否完成

isNewTransaction():判断是新事务

flush():将缓存(seesion)中的数据保存数据库中

Spring有两种事务管理方式:①编程式  ②声明式。

编程式的比较灵活,但是代码量大,存在重复的代码比较多;

而声明式事务管理比编程式更灵活方便。

编程式事务管理(通过模版transactionTemplate):

需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法<bean     id="transactionTemplate"

class="org.springframework.transaction.support.TransactionTemplate">

<property name="transactionManager" ref="transactionManager"></property>

</bean>

(引入配置好的事务管理器        transactionManager

I:DataSourceTransactionManager II:HibernateTransactionManager 注入dataSource)

声明式事务管理:建立在 AOP 的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

①通过TransactionProxyFactoryBean类生成代理来控制事务

I:配置事务管理器

II:配置TransactionProxyFactoryBean

<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<!-- 配置目标bean,即为哪个bean生成代理 -->

<property name="target" ref="accountService"></property>

<!-- 配置事务管理器 -->

<property name="transactionManager" ref="transactionManager"></property>

<!-- 主要设置为哪些方法添加事务,以及事务的传播方式、隔离级别等 -->

<property name="transactionAttributes">

<props>

<prop key="transfer">+java.lang.ArithmeticException,PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

+表示即使抛出该异常事务同样要提交(异常后面的不提交)

- 表示抛出该异常时需要回滚

 传播行为 [,隔离级别] [,只读属性] [,超时属性] [不影响提交的异常] [,导致回滚的异常]

②使用aop切面管理事务

I:配置事务管理器

II:配置aop

<aop:config>

<aop:pointcut expression="execution(* com.sw.spring.transaction.demo3.*Service.*(..))" id="apointcut"/>

<aop:advisor advice-ref="txAdvice" pointcut-ref="apointcut"/>

</aop:config>

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="transfer" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

基于注解的声明式事务管理(主要用这个)      @Transactional

I:配置事务管理器

II:开启注解事务

<tx:annotation-driven transaction-manager="transactionManager"/>

III:在Service上加上注解:@Transactional

时间: 2024-10-20 21:09:29

Spring中事务管理的相关文章

Spring的事务管理

事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 持久性:一旦结束,数据就永久的保存到数据库 如果不考虑隔离性 脏读:一个事务读到另一个事务未提交数据 不可重复读:一个事务读到另一个事务已经提交数据(update)导致一个事务多次查询结果不一致 虚读:一个事务读到另一个事务已经提交数据(insert)导致一个事务多次查询结果不一致 事务的隔离级别

Spring Boot事务管理(中)

在上一篇 Spring Boot事务管理(上)的基础上介绍Spring Boot事务属性和事务回滚规则 . 4 Spring Boot事务属性 什么是事务属性呢?事务属性可以理解成事务的一些基本配置,描述了事务策略如何应用到方法上.事务属性包含了5个方面,如图所示,它们定义于TransactionDefinition接口类   1. 事务隔离级别 隔离级别是指若干个并发事务之间的隔离程度. Spring Boot的隔离级别被封装在枚举类Isolation,枚举值取自接口TransactionDe

spring与事务管理

就我接触到的事务,使用最多的事务管理器是JDBC事务管理器.现在就记录下在spring中是如何使用JDBC事务管理器 1)在spring中配置事务管理器 <!-- JDBC事务 -->    <bean id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property

Spring初学之spring的事务管理xml

所有的java类都是用的上一篇文章:Spring初学之spring的事务管理 不同的是,这时xml配置事务,所以就要把java类中的那些关于spring的注解都删掉,然后在xml中配置,ApplicationContext.xml如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans&q

[原创]java WEB学习笔记109:Spring学习---spring中事物管理

博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ------------------------------------------------------------------------------------------------------------------

spring笔记--事务管理之声明式事务

事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使用事务: 作为一个受欢迎的企业应用框架,Spring在不同的事务管理API上定义了一个抽象层,而开发时不必了解底层的事务管理API,就可以使用Spring的事务管理机制. Spring既支持编程式的事务管理,也支持声明式的事务管理,大多数情况我们选择后者. 编程式事务管理:将事务管理代码嵌入到业务代

Spring初学之spring的事务管理注解

spring的事务管理,本文的例子是:比如你需要网购一本书,卖书的那一方有库存量以及书的价格,你有账户余额.回想我们在编程中要实现买书这样的功能,由于你的账户表和书的库存量表肯定不是同一张数据库表,所以必定会有一个先后,要么先将账户余额扣除书的价格,紧接着将书的库存量减一,要么反过来.那么问题来了,假如我们先将你的账户余额减掉,然后发现书的库存不足,这时怎么办呢,这就需要事务了,当我们发现书的库存不足时就要回滚事务,将你的余额返回去.只要配置了事务,发生了异常,就回滚.这就是事务的回滚.注:新人

深入Spring:自定义事务管理

转自: http://www.jianshu.com/p/5347a462b3a5 前言 上一篇文章讲了Spring的Aop,这里讲一下Spring的事务管理,Spring的事务管理是建立在Aop的基础上的,相比Aop,事务管理的实现耦合性比较小,自定义就比较简单了. 自定义事务 Spring的开启事务管理主要是通过@EnableTransactionManagement注解来实现的.查看源码就会发现,这个注解主要是注入了两个类InfrastructureAdvisorAutoProxyCrea

Spring高级事务管理难点剖析

1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中.这是最常见也是默认的方式. PROPAGATION_SUPPORTS(跟随环境) 支持当前事务,如果当前没有事务,就以非事务方式执行. PROPAGATION_MANDATORY(需要事务) 使用当前的事务,如果当前没有事务,就抛出异