Spring 对于事务管理的支持

关于事务管理的基本概念,查看 http://blog.csdn.net/al_assad/article/details/78808820
JDBC 底层已经提供了对于事务管理的一系列接口和实现类,Spring 对于 JDBC 的事务管理进行了进一步的封装,不仅支持编程式的事务管理,还提供了更加简洁的声明式事务管理;

Spring 事务管理的和核心接口

Spring 事务管理 SPI(Service Provider Interface)的抽象接口主要包括3个核心接口,它们位于 org.springframework.transaction 包中,如下:
  • TransactionDefinition :定义了 Spring 兼容的事务属性,这些属性对事务管理控制的若干方面进行配置 ;
  • PlatformTransactionManager:事务管理器,管理事务的行为,如创建,提交,回滚等;
  • TransactionStatus:代表一个事务的具体运行状态,事务管理器可以以通过该接口获取事务运行期间的状态信息,也可以通过该接口间接的回滚事务;
Spring 事务管理器实现类
Spring 将事务管理的实现细节委托底层具体的持久化实现框架来实现,为不同的持久化框架提供了 PlatformTransactionManager 接口的实现类:
org.springframework.jdbc.dataSource.TransactionManager 使用 Spring JDBC 或 MyBatis 等基于 DataSource 数据源的持久化技术
org.springframework.orm.hibernateX.HibernateTransactionManager 使用 Hibernnate (3.0+)的持久化技术
org.springframework.orm.jpa.JpaTransactionManager 使用 JPA 的持久化技术
org.springframework.orm.jdo.JdoTransactionManager 使用 JDO 的持久化技术
org.springframework.transaction.jta.JtaTransactionManager 具有多个数据源的全局事务使用该事务管理器
在使用 Spring 进行事务管理时,首先要对事务管理器进行配置,常用配置示例如下:
1)Spring JDBC 和 MyBatis
   <!--数据源配置-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"

          p:driverClassName="#{'jdbc.driverClassName'}"

          p:url="#{'jdbc.url'}"

          p:username="#{'jdbc.username'}"

          p:password="#{'jdbc.password'}" />

.....

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

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

          p:dataSource-ref="dataSource" />

2)Hibernate 
 <!--数据源配置,同上-->

<!--配置会话工厂-->

<bean id="sessionFactory" class="org.springframework.hibernate4.LocalSessionFactoryBean" 

      p:dataSource-ref="dataSoucre"

      p:mappingResource="classpath:hibernate.hbm.xml">

    <property name="hibernateProperties">

        <props>

            <prop key="hibernate.dialect">#{'hibernate.dialect'}</prop>

            <prop key="hibernate.show_sql">true</prop>

            <prop key="hibernate.generate_statistics">true</prop>

        </props>

    </property>

</bean>

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

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"

      p:sessionFactory-ref="sessionFactory" />

3)JPA
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"

      p:dataSource-ref="dataSoucre" />

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

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"

      p:entityManagerFactory-ref="entityManagerFactory" />

4)JTA
 <!--通过 jee 命名空间获取 Java EE 应用服务器容器中的数据源 -->

<jee:jndi-lookup id="accountDs" jndi-name="java:comp/env/jdbc/account" />

<jee:jndi-lookup id="orderDs" jndi-name="java:comp/env/jdbc/order" />

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

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

事务同步管理器

Spring 将 JDBC 的 Connection、Hibernate 的 Session 等访问数据的连接或会话对象统称为资源,这些资源在同一时刻是不能多线程共享的,为了让 DAO,Service 类能做到 singleton,Spring 的事务同步管理类 org.springframework.transaction.support.TransactionSynchronizedManager 使用 ThreadLocal类作为基础,为不同的事务线程提供了独立的资源副本;
Spring 为不同的持久化技术提供从TransactionSynchronizedManager 获取对应线程绑定资源的工具类,如下:
org.springframework.jdbc.dataSource.DataSourceUtils Spring JDBC 或 Mybatis
org.springframework.orm.hibernateX.SessionFactoryUtils Hibernate(3.0+)
org.springframework.orm.jpa.EntityManagerFactoryUtils JPA
org.springframework.orm.jdo.PersistenceManagerFactoryUtils JDO
这些工具类都提供了可以获取资源的静态方法,如:
DataSourceUtils.getConnection(DataSoucre dataSoucre):从指定的数据源中获取绑定的Connection;
SessionFactory.getSession(DataSoucre dataSoucre):Hibernate框架中 从指定的数据源中获取把绑定的Session;

事务传播行为

Spring 通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口的方法中,在 TransactionDefinition 接口中规定了7种类型的事务传播行为,他们规定了事务方法之间发生嵌套时事务如何传播;
PROPAGATION_REQUIRED 默认设置,如果当前没有事务,这新建一个事务;如果已经存在一个事务,这加入到该事务中;
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,则以非事务的方式执行;
PROPAGATION_MANDATORY 使用当前事务,如果当前没有事务,则抛出异常;
PROPAGATION_REQUIRED_NEW 新建事务,如果当前存在事务,则将该事务挂起;
PROPAGATION_NOT_SUPPORTED 以非事务的形式执行,如果当前存在事务,则将事务挂起;
PROPAGATION_NEVER 以非事务的形式执行,如果当前存在事务,则抛出异常;
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则执行类似于
PROPAGATION_REQUIRED的操作

Spring 声明式事务的配置

以下示例代码地址:https://gitee.com/assad/springframework-test-dao-transaction
Spring 对于事务的配置方式,除了可以通过 org.springframework.transaction.support.TrasacntionTempalte 使用编程式配置之外,还可以使用声明式进行配置,包括使用XML和注解进行声明式配置;
以下是一个需要被实施事务增强的 service 接口 UserService :
package site.assad.service_tx;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import site.assad.dao.GameDao;

import site.assad.dao.UserDao;

import site.assad.domain.Game;

import site.assad.domain.User;

@Service

public class UserService {

    @Autowired

    private UserDao userDao;

    @Autowired

    private GameDao gameDao;

    public User getUser(final int userid){

        User user = null;

        user = userDao.getUserById(userid);

        return user;

    }

    public void collect(final int userid,final int gameid){

        User user = new User(userid);

        Game game = new Game(gameid);

        userDao.collectGame(user,game);

        gameDao.gameCollected(game,user);

    }

    //public void addUser(..);  省略

    //public void updateUser(..); 省略

}

使用XML配置声明式事务

在Spring 2.0 之前,由于没有引入AOP,只能通过TransactionProxyFactoryBean 代理工厂类进行xml方式的配置,该过程比较繁琐,在Spring 2.0 开始,Spring 引入AOP ,同时提供了使用基于 aop/tx 命名空间的配置(实际开发中更多地使用这种简化的配置方式);
示例代码模块:
site/assad/domain/*(领域对象)
site/assad/dao/*(dao层对象)
site/assad/service_tx/* (service层对象)
site/assad/applicationContext-tx.xml(配置文件)
site/assad/service_tx/*(测试文件)
使用基于aop/tx 命名空间的xml配置文件,对以上 UserService 等织入事务增强切面,代码块如下:
<?xml version="1.0" encoding="UTF-8"?>

<!--使用aop/tx 的 xml 配置方式配置声明式事务-->

<beans ...>

    <!--扫描bean-->

    <context:component-scan base-package="site.assad.dao" />

    <context:component-scan base-package="site.assad.service_tx" />

    <!--属性占位符配置-->

    <context:component-scan base-package="site.assad" />

    <context:property-placeholder location="classpath:site/assad/jdbc.properties" />

    <!--数据源配置-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"

          p:driverClassName="#{'jdbc.driverClassName'}"

          p:url="#{'jdbc.url'}"

          p:username="#{'jdbc.username'}"

          p:password="#{'jdbc.password'}" />

    <!--Jdbc模板配置-->

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"

          p:dataSource-ref="dataSource" />

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

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

          p:dataSource-ref="dataSource" />

    

    <!--使用tx命名空间 配置事务增强-->

    <tx:advice id="txActive" transaction-manager="txManager">

        <tx:attributes>

            <tx:method name="get*" read-only="false" />

            <tx:method name="add*" rollback-for="Exception" />

            <tx:method name="update*" />

            <tx:method name="collect" />

        </tx:attributes>

    </tx:advice>

    <!--使用 schema 的方式配置 事务增强的 aop 切面-->

    <aop:config proxy-target-class="true">

        <!--定义aop切点-->

        <aop:pointcut id="serviceMethod" expression="execution(* site.assad.service_tx.*Service.*(..))" />

        <!--织入事务增强-->

        <aop:advisor pointcut-ref="serviceMethod" advice-ref="txActive" />

    </aop:config>

</beans>

这种配置方式可以在 Service 类不需要侵入任何代码的情况下,完成事务增强切面的织入;
其中配置 <tx:active>事务增强切面中 <tx:method > 元素常用的属性如下:
属性 默认值 说明
name 制定方法切点,如:“get*”,“collect”,“on*Event”等
propagation REQUIRED 指定事务传播行为,候选值为:
REQUIRED、SUPPORTS、MANDATORY、REQUIRED_NEW、NOT_SUPPORTED、NEVER、NESTED
isolation DEFAULT 事务隔离级别,候选值为:
DEFAULT、READ_UNCOMMITED、READ_COMMIT、REPEATABLE_READ、SERIALIZABLE 见:事务管理
timeout -1 事务超时时间(单位秒)
read-only false 事务是否只读
rollback-for 所有运行期异常回滚 触发事务回滚的 Exception,用异常名称片段进行匹配,可以设置多个,中间用 “,” 隔开
no-rollback-for 所有检查异常类型不回滚 不触发事务回滚的 Exception;
其中除了 name 属性为必要属性外,其他属性都可选用;

使用@Transactional注解配置声明式事务

Spring 的声明式事务,除了支持 XML 进行配置,还支持使用 @Transactional 注解进行配置,@Transactional 注解可以使用在接口定义/接口方法、类定义、类的public方法上;
Spring 建议在业务实现类上使用 @Transactional 注解,不推荐在接口定义/接口方法上使用,这是由于注解无法继承,在继承实现接口时,可能会留下一些容易被忽略的隐患;
示例代码模块:
site/assad/domain/*(领域对象)
site/assad/dao/*(dao层对象)
site/assad/service_anno/* (service层对象)
site/assad/applicationContext-anno.xml(配置文件)
site/assad/service_anno/*(测试文件)
以下是 UserDao 使用了注解进行事务管理切点的标注:
package site.assad.service_tx;

@Service

@Transactional  //在类级别上标注事务增强切点

public class UserService {

    @Autowired

    private UserDao userDao;

    @Autowired

    private GameDao gameDao;

    public User getUser(final int userid){

        User user = null;

        user = userDao.getUserById(userid);

        return user;

    }

    public void collect(final int userid,final int gameid){

        User user = new User(userid);

        Game game = new Game(gameid);

        userDao.collectGame(user,game);

        gameDao.gameCollected(game,user);

    }

    //public void addUser(..);  省略

    //public void updateUser(..); 省略

}

@Transactional 注解常用的属性如下:
属性 默认值 说明
propagation REQUIRED 指定事务传播行为,候选值为:
REQUIRED、SUPPORTS、MANDATORY、REQUIRED_NEW、NOT_SUPPORTED、NEVER、NESTED
如:@Transactional(propagation=Propagation.REQUIRED)
isolation DEFAULT 事务隔离级别,候选值为:
DEFAULT、READ_UNCOMMITED、READ_COMMIT、REPEATABLE_READ、SERIALIZABLE 见:03. 事务管理
如:@Transactional(isolation=Isolation.READ_COMMIT)
timeout -1 事务超时时间(单位秒)
如:@Transactional(timeout=10)
readOnly false 事务是否只读
如:@Transactional(readOnly=true)
rollbackFor 所有运行期异常回滚 触发事务回滚的 Exception,类型为Class<T>
如:@Transactional(rollbackFor={SQLException.class})
rollbackForClass 同上 如:@Transactional(rollbackForClass={"SQLException"})
noRollbackFor 所有检查异常类型不回滚 不触发事务回滚的 Exception;
noRollbackForClass 同上 同上
在使用 @Transactional 注解后,需要在配置文件中配置注解织入驱动,如下:
<?xml version="1.0" encoding="UTF-8"?>

<beans ...>

    <!--扫描bean-->

    <context:component-scan base-package="site.assad.dao" />

    <context:component-scan base-package="site.assad.service_tx" />

    <!--属性占位符配置-->

    <context:component-scan base-package="site.assad" />

    <context:property-placeholder location="classpath:site/assad/jdbc.properties" />

    <!--数据源配置-->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"

          p:driverClassName="#{'jdbc.driverClassName'}"

          p:url="#{'jdbc.url'}"

          p:username="#{'jdbc.username'}"

          p:password="#{'jdbc.password'}"/>

    <!--Jdbc模板配置-->

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"

          p:dataSource-ref="dataSource" />

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

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

          p:dataSource-ref="dataSource" />

    <!--对标注 @Transactional 的 bean 织入事务增强-->

    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />

</beans>

Spring DAO(3):Spring 事务管理相关推荐

  1. 在Spring中使用JTA事务管理

    在Spring中使用JTA事务管理 Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻.但是很大部分人都还 ...

  2. spring配置c3p0连接池、spring的声明式事务管理

    一.spring配置c3p0连接池: 1.导入maven依赖: <!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --> & ...

  3. Spring基于Annotation实现事务管理

    在 Spring 中,除了使用基于 XML 的方式可以实现声明式事务管理以外,还可以通过 Annotation 注解的方式实现声明式事务管理. 使用 Annotation 的方式非常简单,只需要在项目 ...

  4. Spring 注解方式实现 事务管理

    2019独角兽企业重金招聘Python工程师标准>>> 使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间 <beans xmlns="h ...

  5. 全面分析 Spring 的编程式事务管理及声明式事务管理(转)

    摘要 Spring 的事务管理是 Spring 框架中一个比较重要的知识点,该知识点本身并不复杂,只是由于其比较灵活,导致初学者很难把握.本教程从基础知识开始,详细分析了 Spring 事务管理的使用 ...

  6. 全面分析 Spring 的编程式事务管理及声明式事务管理--转

    开始之前 关于本教程 本教程将深入讲解 Spring 简单而强大的事务管理功能,包括编程式事务和声明式事务.通过对本教程的学习,您将能够理解 Spring 事务管理的本质,并灵活运用之. 先决条件 本 ...

  7. spring的annotation-driven配置事务管理器详解

    来源:http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html 这篇文章是我从ITeye上复制来的,看了一遍,觉得很深刻,决定把他复制来,对原作者表示感 ...

  8. spring 的4种事务管理(1种编程式+3种声明式)

    见:http://blog.csdn.net/sinat_25926481/article/details/48208619 Spring的4种事务管理(1种编程式事务+三种声明事务) 一.Sprin ...

  9. Spring框架声明式事务管理

    Spring框架声明式事务管理 底层就是AOP原理,面向切面编程 在不修改源码的情况下,对方法进行增强 Spring框架事务管理相关类和API PlatformTransactionManager 平 ...

  10. Spring的4种事务管理(1种编程式事务+三种声明事务)

    2019独角兽企业重金招聘Python工程师标准>>> Spring的4种事务管理(1种编程式事务+三种声明事务) 一.Spring事务的介绍 二.编程式事务xml的配置 注入后直接 ...

最新文章

  1. rsync服务同步,linux日志,screen工具
  2. iOS 搜狗输入法键盘唤不出的解决办法
  3. [Spring5]IOC容器_Bean管理_bean的作用域和bean的生命周期
  4. 软件工程师 VS 硬件工程师
  5. python爬虫和八爪鱼哪个快_【后端开发】python爬虫和八爪鱼哪个快
  6. 关于 Jason.NET 的质问
  7. 蓝桥杯试题java_java蓝桥杯试题
  8. php修改头像接口,php如何修改头像?
  9. 台式计算机m.2的参数,联想启天M系列
  10. 算法与数据结构学习资源大搜罗——良心推荐
  11. c语言gets和puts的区别,C 语言 gets()和puts()
  12. 红米Note3全网通开发版(MIUI10 8.11.22 安卓6)获取完整root权限
  13. java 级联删除_JPA级联删除
  14. 微信公众号回复小程序链接
  15. 类图之实体之间的关系
  16. python余弦函数_Python cos() 函数
  17. 杰里最新的 授权工具版本【篇】
  18. PWM整流器仿真模型,SVPWM调制方式,空间矢量调制,仿真模型。 PWM整流器matlab仿真模型,SVPWM调制
  19. 引用类型属性自动注入-byName,byType,多个配置文件
  20. 浪潮云海OS C位出道 融合开放基础设施呼之欲出

热门文章

  1. Outlook将邮件内容中的数据以表格形式发送
  2. 歌华有线宽带在Windows XP和Fedora Linux Core 6下的配置
  3. 【ISO15765_UDSOBD诊断】-01-概述
  4. nvme命令中prp_蛋蛋读NVMe之三
  5. WinCE开机logo调试小记
  6. 诚之和:劳斯莱斯、奔驰流量营销接连“翻车”
  7. 又是一年年关至,往事历历在心头
  8. 第六章 恶意代码与防护
  9. The dependencies of some of the beans in the application context form a cycle 循环依赖异常处理
  10. 如何查到营业执照_如何查询营业执照信息