声明式事务管理(基于AOP)

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 05:18   554   0

什么是事务

逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败。

一个Spring事务管理的程序

  1. 创建AccountDao接口,其中包含一个转账方法
    AccountDAO接口
 public interface AccountDAO{
  public void transfer(String outUser, String inUser, Double money);
 }
 

AccountDAOImpl实现类

public class AccountDAOImpl implements AccountDAO{
  @Override
 public void transfer(String outUser, String inUser, Double money){
  this.jdbcTemplate.update("update account set balance = balance + ?"+"where username = ? ", money, inUser);
  int i=1/0;
  this.jdbcTemplate.update("update account set balance = balance - ? where username= ? ",money, outUser);
}
}
  1. 配置Spring配置文件applicationContext.xml文件
    <!-- 1.配置数据源 -->
    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <!--数据库驱动 -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <!--连接数据库的url -->
  <property name="url" value="jdbc:mysql://localhost/spring" />
  <!--连接数据库的用户名 -->
  <property name="username" value="root" />
  <!--连接数据库的密码 -->
  <property name="password" value="root" />
   </bean>
   <!-- 2.配置JDBC模板 -->
   <bean id="jdbcTemplate" 
          class="org.springframework.jdbc.core.JdbcTemplate">
   <!-- 默认必须使用数据源 -->
   <property name="dataSource" ref="dataSource" />
   </bean>
   <!--3.定义id为accountDao的Bean -->
   <bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
   <!-- 将jdbcTemplate注入到AccountDao实例中 -->
   <property name="jdbcTemplate" ref="jdbcTemplate" />
   </bean> 
   <!-- 4.事务管理器,依赖于数据源 -->
   <bean id="transactionManager" class=
   "org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
   </bean> 
   <!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
   <tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
   <!-- name:*表示任意方法名称 -->
   <tx:method name="*" propagation="REQUIRED" 
                           isolation="DEFAULT" read-only="false" />
  </tx:attributes>
 </tx:advice>
 <!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
 <aop:config>
  <!-- 切入点 -->
  <aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))"
   id="txPointCut" />
  <!-- 切面:将切入点与通知整合 -->
  <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
 </aop:config>
  1. 测试:当调用转账方法时,如果发生异常,因为配置了事务管理器,账户余额应该都不变;如果没有配置事务,会发现其中转账一方金额增加,另一个金额不变,这在转账中是不被允许的。
 @Test
 public void annotationTest(){
     ApplicationContext applicationContext = 
 new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
     // 获取AccountDao实例
     AccountDao accountDao = 
 (AccountDao)applicationContext.getBean("accountDao");
     // 调用实例中的转账方法
     accountDao.transfer("Jack", "Rose", 100.0);
     // 输出提示信息
     System.out.println("转账成功!");
 }

基于注解的事务管理

步骤

  1. 在Spring容器中注册事务注解驱动
<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 在需要使用事务的Spring Bean类或者Bean类的方法上添加注解@Transactional。在类上对所有方法都有效,在某个方法上,只对该方法有效。

@Transactional注解的参数和描述

参数名称 描述
value 指定要使用的事务管理器
transactionManager 指定事务的限定符值
isolation 指定事务的隔离级别
noRollbackFor 特定异常不回滚
noRollbackForClassName 特定的多个异常不回滚
propagation 传播行为
read-only 事务是否只读
rollbackFor 遇到特定异常强制回滚事务
rollbackForClassName 遇到多个特定异常强制回滚事务
timeout 事务超时时长

事务的传播行为

一个基于注解的事务例子

  1. Spring配置事务注解驱动
<!-- 1.配置数据源 -->
    <bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <!--数据库驱动 -->
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <!--连接数据库的url -->
  <property name="url" value="jdbc:mysql://localhost/spring" />
  <!--连接数据库的用户名 -->
  <property name="username" value="root" />
  <!--连接数据库的密码 -->
  <property name="password" value="root" />
 </bean>
 <!-- 2.配置JDBC模板 -->
 <bean id="jdbcTemplate" 
            class="org.springframework.jdbc.core.JdbcTemplate">
  <!-- 默认必须使用数据源 -->
  <property name="dataSource" ref="dataSource" />
 </bean>
 <!--3.定义id为accountDao的Bean -->
 <bean id="accountDao" class="com.itheima.jdbc.AccountDaoImpl">
  <!-- 将jdbcTemplate注入到AccountDao实例中 -->
  <property name="jdbcTemplate" ref="jdbcTemplate" />
 </bean>
 <!-- 4.事务管理器,依赖于数据源 -->
 <bean id="transactionManager" class=
     "org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
 </bean> 
    <!-- 5.注册事务管理器驱动 -->
 <tx:annotation-driven transaction-manager="transactionManager"/>
  1. 在方法上添加注解
public class AccountDaoImpl implements AccountDao {
 // 声明JdbcTemplate属性及其setter方法
 private JdbcTemplate jdbcTemplate;

 public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
  this.jdbcTemplate = jdbcTemplate;
 }
 
 @Transactional(propagation = Propagation.REQUIRED, 
            isolation = Isolation.DEFAULT, readOnly = false)
 public void transfer(String outUser, String inUser, Double money) {
     // 收款时,收款用户的余额=现有余额+所汇金额
     this.jdbcTemplate.update("update account set balance = balance +? "
             + "where username = ?",money, inUser);
     // 模拟系统运行时的突发性问题
     int i = 1/0;
     // 汇款时,汇款用户的余额=现有余额-所汇金额
     this.jdbcTemplate.update("update account set balance = balance-? "
             + "where username = ?",money, outUser);
 }

}

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP