Spring中的事务管理

北慕城南 提交于 2020-03-15 09:20:16

一、事务简介

        事务管理是企业级应用程序开发中必不可少的技术,  用来确保数据的完整性和一致性. 
        事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
        事务的四个关键属性(ACID)
               原子性(atomicity): 事务是一个原子操作, 由一系列动作组成. 事务的原子性确保动作要么全部完成要么完全不起作用.
                一致性(consistency): 一旦所有事务动作完成, 事务就被提交. 数据和资源就处于一种满足业务规则的一致性状态中.
                隔离性(isolation): 可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏.
                持久性(durability): 一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中
 

Spring 中的事务管理

        作为企业级应用程序框架,Spring 在不同的事务管理 API 之上定义了一个抽象层. 而应用程序开发人员不必了解底层的事务管理 API, 就可以使用 Spring 的事务管理机制.
        Spring 既支持编程式事务管理, 也支持声明式的事务管理. 
                编程式事务管理: 将事务管理代码嵌入到业务方法中来控制事务的提交和回滚. 在编程式管理事务时, 必须在每个事务操作中包含额外的事务管理代码. 
                声明式事务管理: 大多数情况下比编程式事务管理更好用. 它将事务管理代码从业务方法中分离出来, 以声明的方式来实现事务管理.事务管理作为一种横切关注点, 可以通过 AOP 方法模块化. Spring 通过 Spring AOP 框架支持声明式事务管理.
 

Spring 中的事务管理器

        Spring 从不同的事务管理 API 中抽象了一整套的事务机制.开发人员不必了解底层的事务 API, 就可以利用这些事务机制. 有了这些事务机制, 事务管理代码就能独立于特定的事务技术了.
        Spring 的核心事务管理抽象是platform TransactionManage它为事务管理封装了一组独立于技术的方法. 无论使用 Spring 的哪种事务管理策略(编程式或声明式), 事务管理器都是必须的.
 

Spring 中的事务管理器的不同实现

        DataSoureTransactionManage :在应用程序中只需要处理一个数据源, 而且通过 JDBC 存取
        Jta TransactionManage : 在 JavaEE 应用服务器上用 JTA(Java Transaction API) 进行事务管理
        HibernateTransactionManage :用 Hibernate 框架存取数据库
……
事务管理器以普通的 Bean 形式声明在 Spring IOC 容器中
 

用 @Transactional 注解声明式地管理事务

        除了在带有切入点, 通知和增强器的 Bean 配置文件中声明事务外, Spring 还允许简单地用@Transactional 注解来标注事务方法. 
        为了将方法定义为支持事务处理的, 可以为方法添加 @Transactional 注解. 根据 Spring AOP 基于代理机制,只能标注公有方法.
        可以在方法或者类级别上添加 @Transactional 注解. 当把这个注解应用到类上时, 这个类中的所有公共方法都会被定义成支持事务处理的. 
        在 Bean 配置文件中只需要启用<tx:annotation-driven> 元素, 并为之指定事务管理器就可以了. 
如果事务处理器的名称是 transactionManager, 就可以在<tx:annotation-driven> 元素中省略 transaction-manager 属性. 这个元素会自动检测该名称的事务处理器.
 
                @Transactional
                @Override
                public void purchase(String username, String isbn) {
                        
                        bookShopDao.updateBookStock(isbn);
                        bookShopDao.updateUserAccount(username, price);
}
 
                <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
                <property name="dataSource" ref="dataSource"></property>  
                </bean>  
      
                <!-- 2. 配置事务属性 -->  
                <tx:annotation-driven  transaction-manager="transactionManager"/> 
 

二、事务属性

事务传播属性

        当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播. 例如: 方法可能继续在现有事务中运行, 也可能开启一个新事务, 并在自己的事务中运行.
        事务的传播行为可以由传播属性指定. Spring 定义了7  种类传播行为.(一二两种最常用)
                (1)PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
                (2)PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
                (3)PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
                (4)PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
                (5)PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
                (6)PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
                (7)PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
 

事务的隔离级别

        从理论上来说, 事务应该彼此完全隔离, 以避免并发事务所导致的问题. 然而, 那样会对性能产生极大的影响, 因为事务必须按顺序运行. 
        在实际开发中, 为了提升性能, 事务会以较低的隔离级别运行.
        事务的隔离级别可以通过隔离事务属性指定
                1.ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
                2.ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
                3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
                4.ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
                5.ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。 
        事务的隔离级别要得到底层数据库引擎的支持, 而不是应用程序或者框架的支持.
        Oracle 支持的 2 种事务隔离级别:READ_COMMITED , SERIALIZABLE
        Mysql 支持 4 中事务隔离级别.
 

事务回滚属性

        默认情况下只有未检查异常(RuntimeException和Error类型的异常)会导致事务回滚. 而受检查异常不会.
        事务的回滚规则可以通过@Transactional 注解的 rollbackFor 和 noRollbackFor 属性来定义. 这两个属性被声明为 Class[] 类型的, 因此可以为这两个属性指定多个异常类.
                rollbackFor:  遇到时必须进行回滚
                noRollbackFor: 一组异常类,遇到时必须不回滚
        
 

超时和只读属性

        由于事务可以在行和表上获得锁,  因此长事务会占用资源, 并对整体性能产生影响. 
        如果一个事物只读取数据但不做修改, 数据库引擎可以对这个事务进行优化.
                超时事务属性: 事务在强制回滚之前可以保持多久. 这样可以防止长期运行的事务占用资源.
                只读事务属性: 表示这个事务只读取数据但不更新数据, 这样可以帮助数据库引擎优化事务.
        超时和只读属性可以在 @Transactional 注解中定义.超时属性以秒为单位来计算.
        在 Spring 2.x 事务通知中, 超时和只读属性可以在<tx:method> 元素中进行指定.
 
        <!-- 2. 配置事务属性 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
                <tx:attributes>
                        <!-- 根据方法名指定事务的属性 -->
                        <tx:method name="purchase" propagation="REQUIRES_NEW"
isolation =“PROPAGATION_REQUIRES_NEW”rollback-for="java.io.Exception"timeout="30"read-only="true"/>
                </tx:attributes>
        </tx:advice>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!