Spring事务管理原理及方法详解-创新互联
这篇文章主要介绍了Spring事务管理原理及方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
创新互联-专业网站定制、快速模板网站建设、高性价比柘城网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式柘城网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖柘城地区。费用合理售后完善,十载实体公司更值得信赖。事务,在日常开发或者面试中都必定会涉及到。开发工作中,结合数据库开发理解就是:一组dml要么全部成功执行提交,要么因为某一个操作异常,撤销之前所做的成功的操作,整体执行失败。再简单点的一句话:生死与共。
由此,可以看出,事务的必要性:在开发工作中,保证操作数据的安全性。事务的控制也就是保证数据的访问安全性。
一、事务的四大特性
A:原子性(atomicity),对数据的修改,要么全部成功执行,要么全部不执行。
C:一致性(consistency),一旦事务完成,系统必须保证数据职员是满足业务状态的一种一致状态中。很难懂的解释,跟原子性很像。一个事务在操作过程中,数据可能会产生很多中间态,一致性保证中间态对其他事务不可见,因为这些中间态,与事务的开始和结束的状态是不一致的。也就是从一种正确的状态到另一种正确的状态。
I:隔离性(isolation),事务之间的执行应不相互影响,也即事务执行的独立。
D:持久性(durability),事务一旦提交,则对数据库的修改是永久性的。
二、事务的隔离级别
并发环境下,事务可能会存在若干问题:脏读、幻读、不可重复读、第一类更新丢失、第二类更新丢失。
类型 | 说明 | 举例 |
脏读 | A事务读取到了B事务未提交的数据 | A开启事务=>B开启事务,读取账户1000块,取走100块=>A读取账户金额,读取到900=>B回滚事务。此时A读取的余额数据是无效的 |
幻读 | 一个事务里面的操作发现了未被操作的数据 | A开启事务,修改某些数据状态=>B开启事务,执行新增数据并提交=>A事务提交,会出现一条未被修改的数据。 幻读发生的前提是并发事务中发生了新增或者删除动作。 |
不可重复读 | 一个事务中,先后两次读取数据,读到的结果不一致 | A开启事务,读取账户1000块=>B开启事务,读取账户1000块,取出100块并提交事务=>A再读取账户余额,余额900块。 一个事务范围内的两次同样的查询,却返回了两次不同的数据,这就是不可重复读 |
第一类更新丢失 | A事务撤销,把已经提交的B事务的更新的数据覆盖 | A开启事务,读取账户1000块=>B开启事务,读取账户1000块,然后增加100块,提交事务,账户变为1100=>A撤销回滚事务,账户成1000块 |
第二类更新丢失 | A事务提交,把已经提交的B事务的更新的数据覆盖 | A开启事务,读取账户1000块=>B开启事务,读取账户1000块,然后增加100块,提交事务,账户变为1100=>A增加100块,提交事务,账户变为1100。 |
针对并发环境下可能出现的事务问题,于是就出现了隔离级别的解决方案,由低到高依次是:读未提交(Read uncommitted)、读已提交(Read committed)、可重复读(Repeatable read)、串行序列化(serializable)。下表展示出不同的隔离级别,对于脏读、幻读、不可重复读是否会出现。
类型 | 脏读 | 不可重复读 | 幻读 | 说明 |
Read uncommitted | 会 | 会 | 会 | |
Read committed | 不会 | 会 | 会 | |
Repeatable read | 不会 | 不会 | 会 | mysql的默认隔离级别 |
serializable | 不会 | 不会 | 不会 | 最严格的隔离级别,将事务串行化执行,性能低。 |
mysql中查询当前隔离级别:select @@tx_isolation;
三、spring事务支持的隔离级别和传播特性
spring中定义了五种隔离界别和七种传播行为(可以在org.springframework.transaction.TransactionDefinition类中看到详细的解释)
1、spring支持的隔离级别
ISOLATION_DEFAULT:默认级别。一般是使用的是数据库本身的隔离级别(mysql - Repeatable read 、oracle - Read committed)
余下ISOLATION_READ_UNCOMMITTED、ISOLATION_READ_COMMITTED、ISOLATION_REPEATABLE_READ、ISOLATION_SERIALIZABLE分别对应上述数据库隔离级别配置。
2、传播特性
事务的传播特性就是在多个事务方法互相调用的时候,事务该如何在方法之间使用传播:
- PROPAGATION_REQUIRED:如果当前有事务,则加入该事务中。如果没有,则新建事务。
- PROPAGATION_SUPPORTS:如果当前有事务,则加入该事务中。如果没有,则以非事务状态运行。
- PROPAGATION_MANDATORY:如果当前有事务,则加入该事务中。如果没有,则抛出无事务异常
- PROPAGATION_REQUIRES_NEW:新建事务。如果当前存在事务,则挂起该事务。
- PROPAGATION_NOT_SUPPORTED:非事务状态运行。如果当前存在事务,则挂起该事务。
- PROPAGATION_NEVER:非事务状态运行。如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED:如果当前有事务,则嵌套事务(父子事务)执行。如果没有,类似PROPAGATION_REQUIRED处理。
spring默认的传播行为是PROPAGATION_REQUIRED,一般适用于绝大多数的开发工作。
3、事务的超时属性
事务在超过预定时间内还未完成操作,则自动回滚事务。TransactionDefinition 中以int值来表示超时时间,单位是秒,提供的默认值是TIMEOUT_DEFAULT = -1,即永不超时,一直等待操作完成
四、spring事务配置方法
spring并不具体直接的管理事务,而是提供了一个接口org.springframework.transaction.PlatformTransactionManager,该接口中主要定义了三个方法:getTransaction(获取事务)、commit(提交)和rollback(回滚)。
根据不同的持久化策略,spring提供了不同的实现,比如jdbc -
org.springframework.jdbc.datasource.DataSourceTransactionManager、hibernate - org.springframework.orm.hibernate5.HibernateTransactionManager等,在其他的实现可以通过源码去查询。
spring事务使用,可以分为编程式事务和声明式事务。编程式事务每次业务使用都得书写获取事务、设置事务隔离级别和传播特性、提交或回滚事务,代码的重复太高,费时费力,且如果代码的功能性复杂时候,使用编程式变得更加痛苦。而声明式的事务,属于无侵入式的,不会影响主业务流程,且编写上非常简单。所以目前开发工作中,更多的是使用声明式事务。
1、编程式事务
//to do。后续补充
2、声明式事务
声明式事务分为两种:基于aop的织入和@Transactional的注解。
2.1、基于aop的事务织入
之后在servcie中定义方法,最好的就是tx:method中定义的格式开头,就会执行特定的事务。
2.2、注解事务
注解事务第一部分的数据源和事务管理器配置同上,配置文件中需要修改的是开启注解配置:
然后在service编程中,加注解@Transactional即可(建议只在service实现类中加),如下是配置样例,其中的属性可以按需设置:
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ,timeout = 100, readOnly = false, rollbackFor = {},noRollbackFor = {})
另外有需要云服务器可以了解下创新互联建站www.cdcxhl.com,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
分享文章:Spring事务管理原理及方法详解-创新互联
文章链接:http://pwwzsj.com/article/cosiej.html