Spring中的事物、事物管理:
一、什么是事物?
事务:事务是逻辑上的一组操作,要么全都执行,要么全不执行。
见我以前写的。这里不再讲解
二、什么是事物管理?
事务管理:是对于一系列数据库操作进行管理,一个事务包含一个或多个SQL语句,是逻辑管理的工作单元(原子单元)。
所谓的事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。
三、Spring事物管理的构成
事务管理系统:由事务管理器、恢复管理器、锁管理器、死锁管理器、缓存管理器 构成。
四、Spring事物管理涉及的接口有哪些?
如上图,Spring事务管理高层抽象主要有3个:
- TransactionDefinition: 事务定义信息(事务传播行为、事务隔离级别、超时、只读属性、回滚规则)
- PlatformTransactionManager: (平台)事务管理器(用来管理事务,包含事务的提交,回滚)
- TransactionStatus: 事务具体运行状态
所谓的事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。
五、Spring的事物管理器(PlatformTransactionManager)。
Spring本身并不直接管理事务,而是提供了多种事务管理器 ,他们将事务管理的职责委托给Mybatis、Hibernate等持久化机制所提供的相关平台框架的事务来实现。Spring提供的每个事务管理器都会充当某一特定平台(JDBC、Mybatis、Hibernate)的事务实现的门面,这使得用户在Spring中使用事务时,几乎不用关注实际的事务实现是什么。
Spring事务管理器的接口是: org.springframework.transaction.PlatformTransactionManager ,通过这个接口,Spring为各个平台如JDBC、Mybatis、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
Spring提供了许多内置事务管理器实现:
- DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring的JDBC抽象框架、iBATIS或MyBatis框架的事务管理;(DataSourceTransactionManager是基于PlatformTransactionManager接口的实现。下面类同。)
- HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;
- WebLogicJtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持。
- WebSphereUowTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
- JtaTransactionManager:位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器;
Spring不仅提供这些事务管理器,还提供对如JMS事务管理的管理器等,Spring提供一致的事务抽象如下图:
接下来让我们学习一下如何在Spring配置文件中定义事务管理器:
声明对本地事务的支持:
a)JDBC及iBATIS、MyBatis框架事务管理器
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
b)Hibernate事务管理器
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
Spring对全局事务的支持:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/test"/> <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManagerName" value=" java:comp/TransactionManager"/> </bean> </beans>
“dataSource”Bean表示从JNDI中获取的数据源,而txManager是JTA事务管理器,其中属性transactionManagerName指定了JTA事务管理器的JNDI名字,从而将事务管理委托给该事务管理器。
六、Spring的事物定义信息(TransactionDefinition)。
在Spring中,声明式事务是通过事务属性来定义的,事务属性描述了事务策略如何应用到方法上。事务属性包含了5个方面,尽管Spring提供了多种声明式事务的机制,但是所有的方式都依赖这五个参数来控制如何管理事务策略。声明式事务通过传播行为,隔离级别,只读提示,事务超时及回滚规则来进行定义。
Spring事务的传播行为(propagation behavior):
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:
传播行为 | 含义 |
---|---|
Propagation.REQUIRED | 表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则,会启动一个新的事务。这是最常见的选择。 |
Propagation.SUPPORTS | 表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行 |
Propagation.MANDATORY | 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常 |
Propagation.REQUIRED_NEW | 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager(新建事务,如果当前存在事务,把当前事务挂起。) |
Propagation.NOT_SUPPORTED | 表示该方法不应该运行在事务中。如果存在当前事务,在该方法运行期间,当前事务将被挂起。如果使用JTATransactionManager的话,则需要访问TransactionManager |
Propagation.NEVER | 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常 |
Propagation.NESTED | 表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样。注意各厂商对这种传播行为的支持是有所差异的。可以参考资源管理器的文档来确认它们是否支持嵌套事务 |
Propagation.REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
————————————————
七、Spring事物管理的方式?
spring支持编程式事务管理和声明式事务管理两种方式。
-
编程式事务管理(了解)
将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码。
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。 -
声明式事务管理(重点)
大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。
声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
【事务管理小结】
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。
八、声明式事务管理,两种配置方式。
基于@Transactional注解的、 基于tx和aop名字空间的xml配置式
如下都将以mybatis为例。
-
基于@Transactional注解的
1.1.首先来看一段spring.xml代码
<!-- MyBatis begin --> <!-- 1、mybatis文件配置,扫描所有mapper文件 --> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 设置MyBatis核心配置文件 --> <property name="configLocation" value="classpath:resources/mybatis/mybatis-config.xml" /> <!-- 设置数据源 --> <property name="dataSource" ref="dataSource" /> <!-- 它表示我们的Mapper文件存放的位置,当我们的Mapper文件跟对应的Mapper接口处于同一位置的时候可以不用指定该属性的值。 --> <property name="mapperLocations" value="classpath:/mappings/**/*.xml" /> <!-- 那么在Mapper文件里面就可以直接写对应的类名 而不用写全路径名了 --> <!-- 跟mybatis中<typeAliases>作用一样 --> <!-- <property name="typeAliasesPackage" value="com.jeenotes.ssm.pojo"/> --> </bean> <!-- 2、spring与mybatis整合配置,扫描所有dao,在单数据源的情况下可以不写sqlSessionFactoryBeanName --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> <!-- 设置Mapper扫描包,注意扫描的是java-dao-接口文件,不是xml --> <property name="basePackage" value="com.jeenotes.ssm.dao" /> </bean> <!-- 3、定义事务 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 4、开启事务控制的注解支持,配置 Annotation 驱动,扫描@Transactional注解的类定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> <!-- MyBatis end -->
这个文件是spring和mybatis组合时的配置中的,细心的你可能会发现,这1234,这4个配置之间通过id存在关联关系的。
1.2.添加tx名字空间
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
补充一下:添加到spring.xml上边的头部分,至于不明白xmlns,xmlns:xsi,xsi:schemaLocation等含义的同学,可以考虑看一下这篇文章了。
-
基于tx和aop名字空间的xml配置式
同样还是以mybatis为例,主要为aop切面配置,只看xml就可以了
注意:通常这种方式的配置我们都需要再创建一个xml文件:spring-trans.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd"> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 传播行为 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> <!-- 切面 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.jeenotes.ssm.service.*.*(..))" /> </aop:config> </beans>
九、备注:
学习链接1:https://www.cnblogs.com/longshiyVip/p/5061637.html
学习链接2:https://www.cnblogs.com/niceyoo/articles/8732891.html
学习链接3:https://www.jianshu.com/p/7c6d4dbbe8fc
学习链接4:https://www.cnblogs.com/yixianyixian/p/8372832.html
学习链接5:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
学习链接6:https://www.cnblogs.com/chihirotan/p/6758041.html
今天的文章
spring 事物_springmvc常用注解分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/60223.html