【Spring】【笔记】《Spring In Action》第6章 事务管理

本文详细介绍了Spring中的事务管理,包括事务的四个特性:原子性、一致性、隔离性和持久性。重点阐述了这些特性在实际应用中的作用,如确保操作的完整性和数据的一致性,以及如何防止并发操作导致的数据冲突。
摘要由CSDN通过智能技术生成
     事务 transaction : 全有或全无的操作

6.1 理解事务

6.1.1 事务的特性
     这里可以参照数据库原理中对事务的描述
  • 原子性 Atomic:事务是由一个或多个活动组成的一个工作单元,原子性确保事务中的所有操作全部发生或全部不发生
  • 一致性 Consistent:一旦事务完成,无论成功或失败,系统必须确保他所建模的业务处于抑制的状态。
  • 隔离性 Isolated:事务允许多个用户对相同的数据进行操作,每个用户的操作不会与其他用户纠缠到一起。因此,事务应该被彼此隔离,避免发生同步读写相同数据的事情
  • 持久性 Durable:一旦事务完成,事务的结果应该持久化,这样就能从任何的系统崩溃中恢复过来。这一般会设计将结果存储到数据库或其他形式的持久化存储中
     这里事务的概念与数据库理论中的事务是一致的。

6.1.2 Spring对事务管理的支持

     Spring提供了对编码式和声明式事务管理的支持。
     Spring通过回调机制将实际的事务实现从事务性的代码中抽象出来,Spring对事务的支持可以不需要JTA的实现。
JTA,即Java Transaction API,JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据
     如果应用程序只使用一种持久化资源,Spring可以使用持久化机制本身所提供的事务性支持,包括JDBC、Hibernate、JPA。但是如果应用程序的事务跨多个资源,那么Spring会使用第三方的JTA实现来支持分布式(XA)事务。

     编码式事务允许用户在代码中精确定义事务的边界,声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。

6.2 选择事务管理器
      Spring并不直接管理事务,而是提供了多种事务管理器。他们将事务管理的职责委托给JTA或其他持久化机制所提供的平台相关的事务实现。
     Spring的事务管理器:
事务管理器 org.framework.* 使用场景
jca.cci.coonection.CciLocalTransactionManager 使用Spring对JavaEE连接器架构(Java EE Connector Architecture,JCA)和通用客户端接口(Common Client Interface,CCI)提供支持
jdbc.datasource.DataSourceTransactionManager 用于Spring对JDBC抽象的支持,也可用于使用iBATIS进行持久化的场景
jms.connection.JmsTransactionManger 用于JMS1.1+
jms.connection.JmsTransactionManager102 用于JMS1.0.2
orm.hibernate3.HibernateTransactionManager 用于Hibernate3进行持久化
orm.jdo.JdoTransactionManager 用于JDO进行持久化
orm.jpa.JpaTransactionManager 用于Java持久化API(Java Persistence API,JPA)进行持久化
transaction.jta.JtaTransactionManager 需要分布式事务或没有其他的事务管理器满足需求
transaction.jta.OC4JJtaTransactionManager 用于Oracle的OC4J JEE容器
transaction.jta.WebLogicJtaTransactionManager 需要使用分布式事务并且应用程序运行于WebLogic中
transaction.jta.WebSphereUowTransactionManager 需要WebSphere中UOWManager所管理的事务
     要使用事务管理器,需要将其生命在应用程序上下文中。

6.2.1 JDBC事务
     如果在应用程序中直接使用JDBC来进行持久化,DataSourceTransactionManager会处理事务边界。要使用DataSourceTransactionManager,需要如下装配:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"/>
     <property name="dataSource" ref="dataSource"/>
</bean>
     这里dataSource配置成一个名为dataSource Bean的引用,而dataSource是定义在上下文文件中的javax.sql.DataSource Bean。
     DataSourceTransactionManager通过调用java.sql.Connection来管理事务,后者是通过DataSource获取到的。通过调用连接的commit()提交事务,rollback()方法进行回滚。

6.2.2 Hibernate事务
     如果使用Hibernate实现应用程序的持久化,那么需要使用HibernateTransactionManager。需如下配置:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"/>
     <property name="sesionFactory" ref="sessionFactory"/>
</bean>
     sessionFactory属性需要装配一个HibernateSessionFactory。(无论是Spring3.0 还是Spring2.5都不包含对Hibernate2的支持,只有Spring2.0是支持的)
     HibernateTransactionManager将事务管理委托给org.hibernate.Transaction对象,后者是从HibernateSession中获得的。事务成功完成时,HibernateTransactionManager将会调用Transaction对象commit()方法。如果事务失败,Transaction对象的rollback()方法将会被调用

6.2.3JPA事务
     使用JPA 需要用Spring的JpaTransactionManager来处理事务,需要如下配置:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
     <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
     JpaTransactionManager只需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现)。JpaTransactionManager将与由工厂所产生的JPA EntityManager合作来构建事务。。
     JpaTransactionManager支持将事务应用于简单的JDBC操作之中,这些JDBC操作所使用的DataSource与EntityManagerFactory所使用的DataSource必须是相同的。为了做到这一点,JpaTransactionManager必须装配一个JpaDialect的实现。

eg:
EclipseLinkJpaDialect
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
将jpaDialect Bean装配到JpaTransactionManager中
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
     <property name="entityManagerFactory" ref="entityManagerFactory"/>
     <property name="jpaDialect" ref="jpaDialect"/>
</bean>
     JpaDialect实现必须同时支持JPA/JDBC访问。所有Spring所支持的特定厂商JpaDialect实现都提供了对JPA和JDBC混合的支持,而DefaultJpaDialect并不支持。

6.2.4 JTA事务
     在其他事务管理器满足不了、或事务需要跨资源使用时,需要使用JtaTransactionManager:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
     <property name="transactionManagerName" value="java:/TransactionManager" />
</bean>
     JtaTransactionManager将事务管理委托给一个JTA的实现。JTa规定了应用程序与一个或多个数据源协调事务的标砖API。transactionManagerName属性指明了要在JNDI上查找的JTA事务管理器。

6.3 Spring编码事务

eg:

saveSpittle()

public void saveSpittle(Spittle spittle) {
     spitterDao.saveSpittle(spittle);
}
添加编码事务
public void saveSpittle(final Spittle spittle) {
     txTemplate.execute(new TransactionCallback<Void>() {     //这里为什么是Void,不太理解
          public Void doInTransaction(TransactionStatus txStatus) {
               try {
                    spitterDao.saveSpittle(spittle);
               } catch(RuntimeException e) {
                    txStatus.setRollbackOnly();
                    throw e;
               }
               return null;
          }
     });
}

     为了使用TransactionTemplate,需要实现TransactionCallBack接口。因为TransactionCallback只有一个要实现的方法,通常会简单的将其实现为匿名内部类。将事务性的代码放在doInTransaction()方法中。
     调用TransactionTemplate实例的execute()方法时,将会执行TransactionCallback实例中的代码。如果代码遇到了问题,调用TransactionStatus对象的setRollbackOnly()方法将回滚事务。否则,如果doInTransaction()成功返回,事务将会提交。
     TransactionTemplate实例需要注入到SpitterServiceImpl中

<bean id="spitterService" class="com.habuma.spitter.service.SpitterServiceImpl">
     ...
     <property name="transactionTemplate">
          <bean class="org.springframework.transaction.support.TransactionTemplate">
               <property name="transactionManager" ref="transactionManager"/>
          </bean>
     </property>
</bean>
     TransactionTemplate需要注入一个transactionManager。实际上TransactionTemplate使用了PlatformTransactionManager实现来处理特定平台的事务管理细节。这里装配的transactionManager的Bean引用,可以是Spring提供的任意一个事务管理器。

     编程式事务是具有侵入性的。因此,在不需要极小粒度的事务控制时,声明式事务是更好的选择。

6.4 声明式事务
     通过AOP实现。

6.4.1 定义事务的属性
     Spring中,声明式事务是通过 事务属性(transaction attribute)来定义的。是无属性描述了事务策略如何应用到方法上。事务属性包含了五个方面:传播行为、隔离级别、hi滚规则、事务超时、是否只读
     Spring所有的声明式事务机制都依赖这5个参数来控制如何管理实务策略。

传播行为
     propagation behavior。定义客户端与被调用方法之间的事务边界。Spring定义了7种不同的传播行为
传播行为 含义
PROPAGATION_ MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,抛出一个异常
PROPAGATION_NESTED 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独的提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。歌唱声对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确定他们是否支持嵌套式事务
PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前争优一个事务在运行,抛出异常
PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager
PROPAGATION_REQUIRED 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务
PROPAGATION_REQUIRES_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionMangager,则需要访问TransactionManager
PROPAGATION_SUPPORTS 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行。
     
      传播规则规定了,新的事务应该被启动还是挂起、方法是否需要在事务环境中运行。

隔离级别
     isolation level。定义了一个事务可能受其他并发事务影响的程度。理想情况下,事物之间是完全隔离的,但这会导致性能问题。
隔离级别 含义
ISOLATION_DEFAULT 适用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED 允许读取尚未提交的数据变更。可能导致脏读、幻读、不可重复读
ISOLATION_READ_COMMITTED 允许读取并发事务已经提交的数据。可能发生幻读、不可重复度
ISOLATION_REPEATABLE_READ 对同一字段的多次读取结果是一只的,除非数据被本事务自己修改。可能发生幻读
ISOLATION_SERIALIZABLE 完全服从ACID的隔离级别,确保阻止脏读、不可重复度、幻读。最慢的事务隔离级别,通过完全锁定事务相关的数据库表来实现。
     隔离级别定义在org.springframework.transaction.TransactionDefinition接口中
     并不是所有数据源都支持这些隔离级别

只读
     如果食物支队后端的数据库进行读操作,数据库可以利用食物的之独特性来进行一些特定的优化。
     制度优化是在事务启动的时候由数据库实时的,只有对那些具备启动一个新的事务的传播行为的方法,将事务声明为只读才有意义。包括:PROPAGATION_REQUIRED/PROPAGATION_REQUIRES_NEW/PROPAGATION_NESTED

事务超时
     超时始终会在事务开始时启动,只有对那些具备启动一个新事物的传播性为的方法,设置事务超时才有意义。包括:PROPAGATION_REQUIRED/PROPAGATION_REQUIRES_NEW/PROPAGATION_NESTED

回滚规则
     规定哪些异常会导致事务回滚,哪些不会。默认情况下,事务只有在遇到RuntimeException时才会回滚,检查性异常时不会回滚。

6.4.2 在XML中定义事务
     spring提供了一个tx配置命名空间,用来配置Spring中的声明式事务。
      注意,aop命名空间也应该包括在内

     <tx:advice>
<tx:advice id="txAdvice">
     <tx:attributes>
          <tx:method name="save*" propagation="REQUIRED"/>
          <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
     </tx:attribute>
</tx:advice>
     事务属性定义在<tx:attributes>元素中,<tx:method>元素为相应的属性指定参数
     <tx:method>对事务属性的定义:
隔离级别 含义
isolation 指定事务的隔离级别
propagation 事务的传播规则
read-only 指定事务为只读
rollback-for
no-rollback-for
指定事务对于哪些检查性异常应当回滚而不提交
指定事务对于哪些异常应当继续运行而不会滚
timeout 超时时间
     使用<tx:advice>来声明事务时,需要一个事务管理器。根据 约定优于配置,<tx:advice>嘉定事务管理器被声明为一个id为transactionManager的Bean。如果事务管理器配置了其他的id,例如txManager,则需要在transactionmanager属性中明确指定事务管理器的id:
<tx:advice id="txAdvice" transaction-manager="txManager">
     ..
</tx:advice>

     <tx:advice>只是定义了AOP通知,用于把事务边界通知给方法。但是这只是事务通知,而不是完整的事务性切面。需要一个切点来声明那些Bean应该被通知,因此为了完整定义事务性切面,需要定义一个通知器advisor。
eg:
<aop:config>
     <aop:advisor
          point-cut="execution(* *..SpitterService.*(..))"
          advice-ref=" txAdvice"/>
</aop:config>

6.4.3 定义注解驱动的事务
     
<tx:annotaion-driven> //就可以了

     可以通过transactionmanager属性(默认为transactionManager)来指定特定的事务管理器
<tx:annotaion-driven transaction-manager="txManager"/>
   
     <tx:annotaion-driven>元素告诉Spring检查上下文中所有的Bean并查找使用@Transactional注解的Bean,无论这个注解用于类级别还是方法级别。对于每一个使用@Transactional注解的Bean,<tx:annotaion-driven>会自动为它添加事务通知。通知的事务属性时通过@Transaction注解的参数来定义的。
eg:
@Transational(propagation=Propagation.SUPPORTS,readOnly=true)
public class SpitterServiceImpl implements SpitterService {
...
     @Transactional(propagation=PROPGATION.REQUIRED, readOnly=false)
     public void addSpitter(Spitter spitter) {
...
     }
...
}
     
     在类级别上使用@Transactional注解表示所有的方法都支持事务。



第6章小结

     Spring同时支持编码式和声明式的事务管理。无论按一种方式,Spring都将事务管理平台抽象为通用的API,避免了直接与特定的事务管理器实现进行交互。






Spring是掠过Java大地的一阵清风。Spring是以反向控制设计原理为基础,无需EJB而功能依然强大的轻量级J2EE开发框架。Spring大大简化了使用接口开发的复杂性,并且加快和简化了应用系统的开发。使用简单JavaBean就可以得到EJB的强大功能。<br>本书介绍了Spring背后的原理,引领你迅速进入对框架的体验之中。结合简短代码片断和贯穿全书的持续示例,本书向你展示了如何创建简单有效的J2EE应用系统。你将看到如何使用先进的开源工具解决持久层问题,以及如何将你的应用系统与其他流行Web框架集成。你将学习如何使用Spring管理大量的基础设施代码,这样你就可以将注意力集中在真正的问题上——重要的业务需要。<br>本书内容:<br>·使用Hibernate、JDO、iBatis、OJB以及JDBC开发持久层;<br>·声明式事务事务管理;<br>·与其他Web框架集成:Struts、WebWork、Tapestry、Velocity;<br>·访问J2EE服务,如JMS和EJB;<br>·使用AOP解决交叉问题;<br>·企业组应用系统最佳实践。<br>“……一种解释Spring中各个主题的很好途径……我喜欢这本书”<br>——Christian Parker,Adigio公司总裁<br>“……没有其他书籍可以与这本书的实用性相提并论。”<br>——Olivier Jolly,J2EE构架师,Interface SI<br>“我很喜欢这种展示Spring的方式。”<br>——Norman Richards,XDoclet in Action的作者之一<br>“我极力推荐这本书。”<br>——Jack Herrington,Code Generation in Action的作者 <br>----总共8部分rar下载完后解压 -----<br>Spring in Action. 中文版.part1.rar<br>Spring in Action. 中文版.part2.rar<br>Spring in Action. 中文版.part3.rar<br>Spring in Action. 中文版.part4.rar<br>Spring in Action. 中文版.part5.rar<br>Spring in Action. 中文版.part6.rar<br>Spring in Action. 中文版.part7.rar<br>Spring in Action. 中文版.part8.rar<br>
目录 第一部分spring的核心 第1开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 1.3.1依赖注入 1.3.2di应用 1.3.3企业级应用中的依赖注入 1.4应用aop 1.4.1aop介绍 1.4.2aop使用 1.5小结 第2基本bean装配 2.1容纳你的bean 2.1.1beanfactory介绍 2.1.2使用应用上下文 2.1.3bean的生命 2.2创建bean 2.2.1声明一个简单的bean 2.2.2通过构造函数注入 2.3注入bean属性 2.3.1注入简单的数值 2.3.2使用其他的bean 2.3.3装配集合 2.3.4装配空值 2.4自动装配 2.4.1四种自动装配类型 2.4.2混合使用自动和手动装配 2.4.3何时采用自动装配 2.5控制bean创建 2.5.1bean范围化 2.5.2利用工厂方法来创建bean 2.5.3初始化和销毁bean 2.6小结 第3高级bean装配 3.1声明父bean和子bean 3.1.1抽象基bean类型 3.1.2抽象共同属性 3.2方法注入 3.2.1基本的方法替换 3.2.2获取器注入 3.3注入非springbean 3.4注册自定义属性编辑器 3.5使用spring的特殊bean 3.5.1后处理bean 3.5.2bean工厂的后处理 3.5.3配置属性的外在化 3.5.4提取文本消息 3.5.5程序事件的解耦 3.5.6让bean了解容器 3.6脚本化的bean 3.6.1给椰子上lime 3.6.2脚本化bean 3.6.3注入脚本化bean的属性 3.6.4刷新脚本化bean 3.6.5编写内嵌的脚本化bean 3.7小结 第4通知bean 4.1aop简介 4.1.1定义aop术语 4.1.2spring对aop的支持 4.2创建典型的spring切面 4.2.1创建通知 4.2.2定义切点和通知者 4.2.3使用proxyfactorybean 4.3自动代理 4.3.1为spring切面创建自动代理 4.3.2自动代理@aspectj切面 4.4定义纯粹的pojo切面 4.5注入aspectj切面 4.6小结 第二部分企业spring 第5使用数据库 5.1spring的数据访问哲学 5.1.1了解spring数据访问的异常体系 5.1.2数据访问的模板化 5.1.3使用dao支持类 5.2配置数据源 5.2.1使用jndi数据源 5.2.2使用数据源连接池 5.2.3基于jdbc驱动的数据源 5.3在spring里使用jdbc 5.3.1处理失控的jdbc代码 5.3.2使用jdbc模板 5.3.3使用springjdbc的dao支持类 5.4在spring里集成hibernate 5.4.1选择hibernate的版本 5.4.2使用hibernate模板 5.4.3建立基于hibernate的dao 5.4.4使用hibernate3上下文会话 5.5spring和java持久api 5.5.1使用jpa模板 5.5.2创建一个实体管理器工厂 5.5.3建立使用jpa的dao 5.6spring和ibatis 5.6.1配置ibatis客户模板 5.6.2建立基于ibatis的dao 5.7缓存 5.7.1配置缓存方案 5.7.2缓存的代理bean 5.7.3注解驱动的缓存 5.8小结 第6事务管理 6.1理解事务 6.1.1仅用4个词解释事务 6.1.2理解spring事务管理的支持 6.2选择事务管理器 6.2.1jdbc事务 6.2.2hibernate事务 6.2.3jpa事务 6.2.4jdo事务 6.2.5jta事务 6.3在spring中编写事务 6.4声明式事务 6.4.1定义事务参数 6.4.2代理事务 6.4.3在spring2.0里声明事务 6.4.4定义注释驱动事务 6.5小结 第7保护spring 7.1springsecurity介绍 7.2验证用户身份 7.2.1配置providermanager 7.2.2根据数据库验证身份 7.2.3根据ldap仓库进行身份验证 7.3控制访问 7.3.1访问决策投票 7.3.2决定如何投票 7.3.3处理投票弃权 7.4保护web应用程序 7.4.1代理springsecurity的过滤器 7.4.2处理安全上下文 7.4.3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值