­

Spring 框架基础(05):事务管理机制,和实现方式

  • 2019 年 12 月 10 日
  • 筆記

一、Spring事务管理

1、基础描述

Spring事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交和回滚。

Connection conn = DriverManager.getConnection();  try {      // 自动提交设置为false      conn.setAutoCommit(false);      // 执行增删改查操作      // 当操作成功后手动提交      conn.commit();  } catch (Exception e) {      // 出现异常,回滚所有操作      conn.rollback();      e.printStackTrace();  } finally {      conn.colse();  }  

2、事务常见概念

  • 事务描述

事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部成功,要么全部不成功。

  • 特性:ACID
原子性(Atomicity):事务中的多个操作要么都成功要么都失败  一致性(consistency):事务的执行的前后数据的完整性保持一致  隔离性(isolation):事务执行的过程中,不应该受到其他事务的干扰  持久性(durability):事务一旦结束,数据就持久到数据库  
  • 隔离问题

脏读:一个事务读到另一个事务没有提交的数据

不可重复读:一个事务前后多次读取相同数据,数据内容不一致,update场景问题

虚读(幻读):一个事务前后多次读取,数据总量不一致,insert场景问题

  • 隔离级别

read uncommitted:

事务可以读取另一个未提交事务的数据。

read committed

事务要等另一个事务提交后才能读取数据,解决脏读。

repeatable read

在开始读取数据时,事务开启,不再允许修改操作,解决:脏读、不可重复读。

serializable

最高事务隔离级别,事务串行化顺序执行,解决脏读、不可重复读、幻读。但是效率低下,耗数据库性能。

3、事务管理API描述

  • PlatformTransactionManager

平台事务管理器,Spring管理事务,必须使用事务管理器进行事务配置时,核心方法:获取事务,提交事务,回滚事务。

  • TransactionDefinition

该对象封装事务详情(事务定义、事务属性),例如:隔离级别、是否只读、超时时间 等。

  • TransactionStatus

用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。Spring底层根据状态进行相应操作。

4、事务案例SQL语句

CREATE TABLE user_account(    id INT PRIMARY KEY AUTO_INCREMENT,    username VARCHAR(50),    money INT  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;;  INSERT INTO user_account(username,money) VALUES('jack','5000');  INSERT INTO user_account(username,money) VALUES('tom','5000');  SELECT * FROM user_account ;  

二、编程式事务管理

1、核心配置文件

<!-- 配置事物管理器 -->  <bean id="txManager"        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">      <property name="dataSource" ref="dataSource" />  </bean>  <!-- 创建事物模板 -->  <bean id="transactionTemplate"        class="org.springframework.transaction.support.TransactionTemplate">      <property name="transactionManager" ref="txManager" />  </bean>  <!-- 配置转账接口 -->  <bean id="userAccountService"        class="com.spring.mvc.service.impl.UserAccountServiceImpl">      <property name="jdbcTemplate" ref="jdbcTemplate" />      <property name="transactionTemplate" ref="transactionTemplate" />  </bean>  

2、演示案例

@Service  public class UserAccountServiceImpl extends JdbcDaoSupport implements UserAccountService {      // 注入事物模板      private TransactionTemplate transactionTemplate ;      public void setTransactionTemplate(TransactionTemplate transactionTemplate) {          this.transactionTemplate = transactionTemplate;      }      @Override      public void remittance(String remitTer, String receiver, int money) {          transactionTemplate.execute(new TransactionCallbackWithoutResult() {              public void doInTransactionWithoutResult(TransactionStatus arg0) {                  outMoney(remitTer,money);                  // System.out.println(1/0);                  innerMoney(receiver,money);              }          });      }      private void outMoney (String remitTer, int money){          String outSql = "update user_account set money = money - ? where username = ?";          this.getJdbcTemplate().update(outSql, money ,remitTer);      }      private void innerMoney (String receiver, int money){          String inSql = "update user_account set money = money + ? where username = ?";          this.getJdbcTemplate().update(inSql, money,receiver);      }  }  

三、事务代理工厂

1、核心配置

<!-- 配置转账接口 -->  <bean id="userAccountService01"        class="com.spring.mvc.service.impl.UserAccountServiceImpl01">      <property name="jdbcTemplate" ref="jdbcTemplate" />  </bean>  <!-- 配置事务代理工厂 -->  <bean id="proxyAccountService"        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">      <property name="proxyInterfaces" value="com.spring.mvc.service.UserAccountService01" />      <property name="target" ref="userAccountService01" />      <property name="transactionManager" ref="txManager" />      <property name="transactionAttributes">          <props>              <!-- 默认传播行为、隔离级别 -->              <prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>              <!-- 异常仍然提交事务              <prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.Exception</prop>              -->          </props>      </property>  </bean>  

配置说明:

  • proxyInterfaces 代理接口
  • target 代理目标类
  • transactionManager 事务管理器
  • transactionAttributes 事务属性(事务详情)
  • prop.key 指定方法使用当前事务配置

事务行为:

  • PROPAGATION 传播行为
  • ISOLATION 隔离级别
  • readOnly 是否只读
  • -Exception 异常回滚
  • +Exception 异常提交

2、演示案例

@Service  public class UserAccountServiceImpl01 extends JdbcDaoSupport implements UserAccountService01 {      @Override      public void remittance(String remitTer, String receiver, int money) {          outMoney(remitTer,money);          System.out.println(1/0);          innerMoney(receiver,money);      }      private void outMoney (String remitTer, int money){          String outSql = "update user_account set money = money - ? where username = ?";          this.getJdbcTemplate().update(outSql, money ,remitTer);      }      private void innerMoney (String receiver, int money){          String inSql = "update user_account set money = money + ? where username = ?";          this.getJdbcTemplate().update(inSql, money,receiver);      }  }  

3、测试代码

public class Tx_Test_02 {      @Test      public void test1 (){          String xmlPath = "spring-jdbc-tx-02.xml";          ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath);          UserAccountService01 accountService = (UserAccountService01)                                      context.getBean("proxyAccountService");          accountService.remittance("jack","tom",1000);      }  }  

四、XML配置事务

首先配置事务管理器,然后配置事务属性,最后基于AOP编程配置事务切入点。

1、核心配置

<!-- 配置事物管理器 -->  <bean id="txManager"        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">      <property name="dataSource" ref="dataSource" />  </bean>  <!-- 配置转账接口 -->  <bean id="userAccountService01"        class="com.spring.mvc.service.impl.UserAccountServiceImpl01">      <property name="jdbcTemplate" ref="jdbcTemplate" />  </bean>  <!-- 配置事物详情 -->  <tx:advice id="txAdvice" transaction-manager="txManager">      <tx:attributes>          <tx:method name="remittance"                     propagation="REQUIRED"                     isolation="DEFAULT"/>      </tx:attributes>  </tx:advice>  <!-- 事务切入点,基于AOP编程 -->  <aop:config>      <aop:advisor           advice-ref="txAdvice"           pointcut="execution(* com.spring.mvc.service.UserAccountService01.*(..))"/>  </aop:config>  

五、基于事务注解

配置事务管理器,并启动事务注解的支持,在目标类或目标方法添加@Transactional核心注解即可。

1、核心配置

<!-- 配置事物管理器 -->  <bean id="txManager"        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">      <property name="dataSource" ref="dataSource" />  </bean>  <!-- 支持事务注解 -->  <tx:annotation-driven transaction-manager="txManager" />  

2、注解用法

注解写在接口方法上,或者接口实现的方法上效果一样。

public interface UserAccountService02 {      @Transactional(rollbackFor = Exception.class)      void remittance(String remitTer, String receiver, int money) ;  }  

六、源代码地址

GitHub·地址  https://github.com/cicadasmile/spring-mvc-parent  GitEE·地址  https://gitee.com/cicadasmile/spring-mvc-parent