1. Spring 框架的事务管理相关的类和API

  • PlateformTransactionManager 接口: 平台事务管理器(真正管理事务的类);
  • TransactionDefinition 接口: 事务定义信息(事务的隔离级别,传播行为,超时,只读等);
  • TransactionStatus 接口: 事务的状态;
  • 平台事务管理器真正管理事务对象,根据事务定义信息(TransactionDefinition)进行事务管理,在管理事务

    中产生的一些状态记录到TransactionStatus中;

1.1 PlateformTransactionManager 接口中实现类和常用的方法

  1. 接口的实现类

    • 如果使用 Spring 框架的JDBC模板或者MyBatis框架,需要选择DataSourceTransactionManager实现类;
    • 如果使用的是 Hibernate 框架,需要选择HibernateTransactionManager实现类;
  2. 该接口的常用方法
    • void commit(TransactionStatus status)
    • TransactionStatus getTransaction(TransactionDefinition definition)
    • void rollback(TransactionStatus status)

1.2 TransactionDefinition

  1. 事务隔离级别的常量

    • static int ISOLATION_DEFAULT: 采用数据库的默认隔离级别;
    • static int ISOLATION_READ_UNCOMMITTED
    • static int ISOLATION_READ_COMMITTED
    • static int ISOLATION_REPEATABLE_READ
    • static int ISOLATION_SERIALIZABLE
  2. 事务的传播行为常量(一般使用默认值)

    • 事务的传播行为:解决的是业务层之间的方法调用!
    • 保证 A,B 在同一个事务中:
      • PROPAGATION_REQUIRED(默认值): A中有事务,使用A中的事务;如果没有,B会开启一个新的事务,

        将A包含进来(保证A,B在同一个事务中);
      • PROPAGATION_SUPPORTS: A中有事务,使用A中的事务;如果A中没有事务,那么B也不使用事务;
      • PROPAGATION_MANDATORY: A中有事务,使用A中的事务; 如果A中没有事务,抛出异常;
    • 保证 A,B 没有在同一个事务中:
      • PROPAGATION_REQUIRES_NEW: A中有事务,将A中的事务挂起,B创建一个新的事务,

        (保证A,B不在同一个事务中);
      • PROPAGATION_NOT_SUPPORTED: A中有事务,将A中的事务挂起;
      • PROPAGATION_NEVER: A中有事务,抛出异常;
    • PROPAGATION_NESTED: 嵌套事务,当 A 执行之后,就会在这个位置设置一个保存点,如果B没有问题,

      执行通过;如果B出现异常,根据需求回滚(可以回滚到保存点或最初始的状态);

2. 搭建事务管理转账案例的环境

2.1 导入 jar 包

  • Spring 框架的基本开发包(6个);
  • Spring 的传统AOP的开发包
    • spring-aop-4.3.10.RELEASE
    • org.aopalliance-1.10.0 (在 Spring 依赖包中)
  • aspectJ 的开发包
    • org.aspectj.weave-1.6.8.RELEASE.jar (在 Spring 依赖包中)
    • spring-aspects-4.3.10.RELEASE.jar
  • JDBC 模板所需 jar 包
    • mysql-connector-java.jar: MySql 驱动包;
    • Spring-jdbc.jar;
    • Spring-tx.jar: Spring 事务包;
  • c3p0 的 jar 包: com.mchange.v2.c3p0-0.9.1.2.jar

2.2 创建对应的包结构和类

  • com.itheima.demo

    • AccountService
    • AccountServiceImpl
    • AccountDao
    • AccountDaoImpl
  1. // AccountDao.java
  2. public class AccountDao {
  3. // 扣钱
  4. public void outMoney(String out, double money);
  5. // 加钱
  6. public void inMoney(String in, double money);
  7. }
  8. // AccountService.java
  9. public class AccountService{
  10. public void pay(String out,String in, double money);
  11. }
  12. // AccountDaoImpl.java
  13. // 第一种方式, 使用 jdbc 模板类
  14. public class AccountDaoImpl implements AccountDao{
  15. // 使用 jdbc 模板操作数据库
  16. // 在配置文件中注入 jdbcTemplate 对象
  17. private JdbcTemplate jdbcTemplate;
  18. public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
  19. this.jdbcTemplate = jdbcTemplate;
  20. }
  21. // 扣钱
  22. public void outMoney(String out, double money){
  23. jdbcTemplate.update(sql,args);
  24. }
  25. // 加钱
  26. public void inMoney(String out, double money){
  27. jdbcTemplate.update(sql,args);
  28. }
  29. }
  30. // 第二种方式, 继承 JdbcDaoSupport类, 该类中包含 jdbcTemplate,并且提供了 set方法
  31. // applicationContext.xml 中仍需要注入 jdbcTemplate 对象
  32. public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
  33. // 扣钱
  34. public void outMoney(String out, double money){
  35. this.getJdbcTemplate().update(sql,args);
  36. }
  37. // 加钱
  38. public void inMoney(String in, double money){
  39. this.getJdbcTemplate().update(sql,args);
  40. }
  41. }
  42. // 第三种方式: applicationContext.xml 中无需注入 jdtcTemplate 对象
  43. // 只需要注入连接池对象,
  44. // JdbcDaoSupport 类内部,在 jdbcTemplate 对象为 null 时, 根据连接池创建 jdbcTemplate 对象
  45. public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao{
  46. // 扣钱
  47. public void outMoney(String out, double money){
  48. this.getJdbcTemplate().update("UPDATE t_account SET"
  49. +"money = money - ? WHERE name = ?",money,out);
  50. }
  51. // 加钱
  52. public void inMoney(String in, double money){
  53. this.getJdbcTemplate().update("UPDATE t_account SET"
  54. +"money = money - ? WHERE name = ?",money,in);
  55. }
  56. }
  57. // AccountServiceImpl.java
  58. public class AccountServiceImpl implements AccountService{
  59. private AccountDao accountDao;
  60. public void setAccountDao(AccountDao accountDao){
  61. this.accountDao = accountDao;
  62. }
  63. // 实现转账功能
  64. public void pay(String out, String in, double money){
  65. accountDao.outMoney(out,money);
  66. accountDao.inMoney(in,money);
  67. }
  68. }
  69. // 测试类
  70. @RunWith(SpringJUnit4ClassRunner.class)
  71. @ContextConfiguration("classpath:applicationContext.xml")
  72. public class Demo{
  73. @Resource(name="accountService")
  74. private AccountServiceImpl accountService;
  75. @Test
  76. public void fun(){
  77. // 测试支付方法
  78. accountService.pay("张三","李四",100);
  79. }
  80. }

2.3 applicationContext.xml

  1. <!-- 管理c3p0 连接池 -->
  2. <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  3. <property name="driverClass" value="com.mysql.jdbc.Driver"/>
  4. <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mydb1"/>
  5. <property name="user" value="root"/>
  6. <property name="password" value="root"/>
  7. </bean>
  8. <!-- 管理JDBC的模板类 -->
  9. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  10. <property name="dataSource" value="dataSource"/>
  11. </bean>
  12. <!-- 配置业务层和持久层 -->
  13. <bean id="accountService" class="com.itheima.demo.AccountServiceImpl">
  14. <property name="accountDao" value="accountDao"/>
  15. </bean>
  16. <!-- 第一种和第二种方式, 需要注入 jdbcTemplate 对象 -->
  17. <bean id="accountDao" class="com.itheima.demo.AccountDaoImpl">
  18. <property name="jdbcTemplate" value="jdbcTemplate"/>
  19. </bean>
  20. <!-- 第三种方式, 只需要注入连接池 -->
  21. <bean id="accountDao" class="com.itheima.demo.AccountDaoImpl">
  22. <property name="dataSource" ref="dataSource"/>
  23. </bean>

2.4 Spring 框架事务管理的分类

  1. Spring 的编程式事务管理(不推荐使用)

    • 通过手动编写代码的方式完成事务的管理;
  2. Spring 的声明式事务管理(底层采用AOP的技术)
    • 通过一段配置的方式完成事务的管理;
2.4.1 编程式的事务管理
  1. 手动编程的方式来管理事务,需要使用 TransactonTemplate模板类;
  1. // 具体步骤
  2. // 1. 配置一个事务管理器
  3. // Spring 框架使用 PlatFormTransactionManager 接口来管理事务,需要使用到它的实现类
  4. <bean id="transactionManager"
  5. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  6. // 底层操作事务的是 connection, 该对象存放在连接池
  7. // 事务管理器管理事务,需要从连接池中获取 connection 对象
  8. <property name="dataSource" ref="dataSource"/>
  9. </bean>
  10. // 2. 配置事务管理的模板
  11. <bean id="transactionTemplate"
  12. class="org.springframework.transaction.support.TransactionTemplate">
  13. <property name="transactionManager" ref="transactionManager"/>
  14. </bean>
  15. // 3. 在需要进行事务管理的类中,注入事务管理的模板
  16. // 备注: 事务需要在业务层开启
  17. <bean id="accountService" class="com.itheima.demo.AccountServiceImpl">
  18. <property name="accountDao" ref="accountDao"/>
  19. <property name="transactionTemplate" ref="transactionTemplate"/>
  20. </bean>
  21. // 4. 在业务层使用模板管理事务
  22. public void AccountServiceImpl implements AccountService{
  23. private AccountDao accountDao;
  24. public void setAccountDao(AccountDao accountDao){
  25. this.accountDao = accountDao;
  26. }
  27. // 注入事务模板对象
  28. private TransactionTemplate transactionTemplate;
  29. public void setTransactionTemplate(TransactionTemplate transactionTemplate){
  30. this.transactionTemplate = transactionTemplate;
  31. }
  32. // 实现转账功能
  33. public void pay(final String out, final String in, final double money){
  34. transactionTemplate.execute(new TransactionCallbackWithoutResult(){
  35. protected void doInTransactionWithoutResult(TransactionStatus status){
  36. // 扣钱
  37. accountDao.outMoney(out,money);
  38. // 异常
  39. int a = 10 / 0;
  40. // 加钱
  41. accountDao.inMoney(in,money);
  42. }
  43. });
  44. }
  45. }
2.4.2 声明式事务管理
  1. 声明式事务管理:即通过配置文件来完成事务管理(AOP 思想)

    • 基于AspectJ的XML方式;(重点掌握)
    • 基于AspectJ的注解方式;(重点掌握)
基于AspectJ的XML方式
  1. // applicationContext.xml
  2. // 1. 配置一个事务管理器
  3. // Spring 框架使用 PlatFormTransactionManager 接口来管理事务,需要使用到它的实现类
  4. <bean id="transactionManager"
  5. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  6. // 底层操作事务的是 connection, 该对象存放在连接池
  7. // 事务管理器管理事务,需要从连接池中获取 connection 对象
  8. <property name="dataSource" ref="dataSource"/>
  9. </bean>
  10. // 2. 配置事务增强(通知)
  11. <tx:advice id="myAdvice" transaction-manager="transactionManager">
  12. <tx:attributes>
  13. <!--
  14. 可以配置多个 method;
  15. name : 绑定事务的方法名,可以使用通配符;
  16. propagation: 传播行为;
  17. isolation : 隔离级别;
  18. read-only : 缓存是否只读;
  19. timeout : 超时信息;
  20. rollback-for: 发生哪些异常信息回滚;
  21. no-rollback-for: 发生哪些异常,不回滚;
  22. -->
  23. <tx:method name="pay" propagation="REQUIRED"/>
  24. </tx:attributes>
  25. </tx:advice>
  26. // 3. 配置 AOP 切面
  27. // 备注: 如果是自定义的切面,使用<aop:aspect>标签, 如果是系统自带的,使用<aop:advisor>标签
  28. <aop:config>
  29. <aop:advisor advice-ref="myAdvice"
  30. pointcut="execution(public * com.itheima.demo.AccountServiceImpl.pay(..))"/>
  31. </aop:config>
  32. // 4. 持久层配置
  33. <bean id="accountService" class="com.itheima.demo.AccountServiceImpl">
  34. <property name="accountDao" ref="accountDao"/>
  35. </bean>
基于AspectJ的注解方式(重点掌握,这是最简单的方式)
  1. // 1. 配置事务管理器
  2. <bean id="transactionManager"
  3. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  4. <property name="dataSource" ref="dataSource"/>
  5. </bean>
  6. // 2. 开启注解事务
  7. <tx:annotation-driven transaction-manager="transactionManager"/>
  8. // 3. 在业务层上添加一个注解: @Transactional
  9. // AccountServiceImpl.java
  10. // 如果在这个类上添加注解, 类中的所有方法全部都有事务
  11. @Transactional
  12. public class AccountServiceImpl implements AccountService{
  13. private AccountDao accountDao;
  14. public void setAccountDao(AccountDao accountDao){
  15. this.accountDao = accountDao;
  16. }
  17. // 实现转账功能
  18. // 如果在方法上添加,只有该方法有事务
  19. @Transactional
  20. public void pay(String out, String in, double money){
  21. accountDao.outMoney(out,money);
  22. accountDao.inMoney(in,money);
  23. }
  24. }

参考资料

Spring 框架的事务管理的更多相关文章

  1. Spring框架之事务管理

    Spring框架之事务管理 一.事务的作用 将若干的数据库操作作为一个整体控制,一起成功或一起失败. 原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 一致性:指事务前后 ...

  2. Spring框架的事务管理之编程式的事务管理(了解)

    1. 说明:Spring为了简化事务管理的代码:提供了模板类 TransactionTemplate,所以手动编程的方式来管理事务,只需要使用该模板类即可!!2.手动编程方式的具体步骤如下: 1.步骤 ...

  3. Spring框架的事务管理相关的类和API

    1. PlatformTransactionManager接口 -- 平台事务管理器.(真正管理事务的类).该接口有具体的实现类,根据不同的持久层框架,需要选择不同的实现类! 2. Transacti ...

  4. Spring框架的事务管理之基于AspectJ的XML方式(重点掌握)

    1. 步骤一:恢复转账开发环境(转账开发环境见“https://www.cnblogs.com/wyhluckdog/p/10137283.html”) 2.步骤二:引入AOP的开发包3.步骤三:引入 ...

  5. Spring框架的事务管理的分类

    1. Spring的事务管理的分类 1. Spring的编程式事务管理(不推荐使用) * 通过手动编写代码的方式完成事务的管理(不推荐) 2. Spring的声明式事务管理(底层采用AOP的技术) * ...

  6. (三)Spring框架之事务管理

    一.编程式事务管理 Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,事务管理器接口PlatformT ...

  7. Spring框架的事务管理有哪些优点?

    它为不同的事务API  如 JTA,JDBC,Hibernate,JPA 和JDO,提供一个不变的编程模式. 它为编程式事务管理提供了一套简单的API而不是一些复杂的事务API如 它支持声明式事务管理 ...

  8. Spring 框架的事务管理有哪些优点?

    它为不同的事务 API 如 JTA,JDBC,Hibernate,JPA 和 JDO,提供 一个不变的编程模式. 它为编程式事务管理提供了一套简单的 API 而不是一些复杂的事务 API 它支持声明式 ...

  9. Spring框架的事务管理之基于AspectJ的注解方式(重点掌握,最简单的方式)

    1. 步骤一:恢复转账的开发环境(具体开发环境实现见:https://www.cnblogs.com/wyhluckdog/p/10137283.html)2. 步骤二:applicationCont ...

随机推荐

  1. Nginx(一):linux下安装nginx与配置

    linux系统为Centos 64位 准备目录 [root@instance-3lm099to ~]# mkdir /usr/local/nginx [root@instance-3lm099to ~ ...

  2. 多线程-Thread与Runnable源码分析

    Runnable: @FunctionalInterface public interface Runnable { /** * When an object implementing interfa ...

  3. Sublime Text 2 入门与总结

    Sublime Text 2 入门与总结   首语 :    考完试,但又没什么兴趣做课程设计,蛋疼的弄点软件入门的介绍,希望给各位还在吃香蕉的程序猿带来一点启示...   代码编辑器,就像武侠中的武 ...

  4. python之读取Excel 文件

    # -*- coding: utf-8 -*- """ Created on Thu May 24 13:53:10 2018 @author: Frank " ...

  5. SMP

    SMP(Symmetrical Multi-Processing):对称多处理技术,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构. 在smp系统中,所有的CP ...

  6. WEB前端面试题 分别使用2个、3个、5个DIV画出一个大的红十字

    <!DOCTYPE html> <!--两个DIV--> <html> <body> <div style="width:100%;he ...

  7. ZThread在Windows下打印若干DEBUG信息到console的原因

    代码见这篇随笔 在Windows下的运行结果:ZThread打印了一堆东西(并不是我写的) 文件结构: 最开始我以为是编译选项没弄对,同样的代码放到Linux下编译,还是打印这些信息 注意我在Linu ...

  8. The Definitive Guide To Django 2 学习笔记(九) 第五章 模型 (一)数据库访问

    以MySql数据库为例,先到http://dev.mysql.com/downloads/connector/python/处下载MysqlConnector for python的连接器. from ...

  9. Risk UVA - 12264 拆点法+最大流+二分 最少流量的节点流量尽量多。

    /** 题目:Risk UVA - 12264 链接:https://vjudge.net/problem/UVA-12264 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai ...

  10. golang mongodb查找find demo

    使用gopkg.in/mgo.v2库操作,插入操作主要使用mongodb中Collection对象的Find方法,函数原型: func (c *Collection) Find(query inter ...