Spring事务管理

一、什么是事务

事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败。

二、事务的特性

原子性、一致性、隔离性、持久性
1. 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
2. 一致性:事务前后数据的完整性必须保持一致。
3. 隔离性:指的是多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事物之间数据要相互隔离。
4. 持久性:一个事物一旦被提交了,他对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响。

三、Sping接口介绍

  1. PlatformTransactionManager 事务管理器
    Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现

    这里写图片描述

一般使用DatasourceTransactionManager和HibernateTransactionManager接口
2. TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
如果不考虑隔离性,会引发安全问题如下:
脏读、不可重复读、幻读。

脏读:
一个事务读取到了另一个事物改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。

不可重复读:
在同一个事务中,多次读取同一数据返回的结果有所不同。

幻读:
一个事务读取了几行记录后,另一个事务插入了一些记录,再后来的查询中,第一个事务就会发现有些原来没有的记录。产生了幻读现象。

数据库提供了四个隔离界别

这里写图片描述

MySQL默认采用REPEATABLE_READ隔离级别
Oracle默认READ_COMMITTED隔离界别
这里写图片描述
出现复杂情况:调用Service1.aaa()和Service2中的bbb(),才能给完成一个

事务的传播行为:解决业务层方法之间的相互调用的问题
事务的传播行为有七种:如图
这里写图片描述

3.TransactionStatus 事务具体运行状态

转账为例环境搭建

  • 创建数据库,导入初始数据
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `money` double DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `account` VALUES ('1', 'aaa', '1000');
INSERT INTO `account` VALUES ('2', 'bbb', '1000');
INSERT INTO `account` VALUES ('3', 'ccc', '1000');
  • 导入基本jar包
    <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>com.mchange</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.5.2</version>
        </dependency>
        <dependency>
          <groupId>aopalliance</groupId>
          <artifactId>aopalliance</artifactId>
          <version>1.0</version>
        </dependency>
        <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.1.1</version>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
        </dependency>
        <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.7.3</version>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.6</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
          <version>4.3.11.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>4.3.10.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>4.0.6.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>4.3.10.RELEASE</version>
        </dependency>
      </dependencies>
  • 面向接口编程 创建Service
/**
 - Created by Zhuang on 2018/4/23.
 - 转账案例的业务层接口
 */
public interface AccountService {
    /**
     *
     * @param out   :转出账号
     * @param in    :转入账号
     * @param money :转账金额
     */
    public void transfer(String out,String in,Double money);
}
/**
 - Created by Zhuang on 2018/4/23.
 - 转账案例的业务层的实现类
 */
public class AccountServiceImpl implements AccountService {
    //注入DAO类
    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out,money);
        accountDao.inMoney(in,money);
    }
}
  • 创建Dao层
/**
 - Created by Zhuang on 2018/4/23.
 - 转账案例的DAO层接口
 */
public interface AccountDao {
    /**
     *
     * @param out   :转出账号
     * @param money :转账金额
     */
    public void outMoney(String out,Double money);

    /**
     *
     * @param in    :转入账号
     * @param money :转账金额
     */
    public void inMoney(String in,Double money);
}
/**
 - Created by Zhuang on 2018/4/23.
 - 转账案例的DAO层的实现类
 */
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
    @Override
    public void outMoney(String out, Double money) {
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql,money,out);
    }

    @Override
    public void inMoney(String in, Double money) {
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql,money,in);
    }
}

四、编程式的事务控制

  • 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
</bean>
  • 配置事务管理的模板:Spring为了简化事务管理的代码而提供的类
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
</bean>
  • 向accountService类里注入事务管理的模板
<!--配置业务层的类-->
<bean id="accountService" class="cn.jxufe.spring.demo1.service.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"/>
    <property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
  • 事务控制
public void transfer(final String out,final String in,final Double money) {
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            accountDao.outMoney(out,money);
            //int i = 1 / 0;
            accountDao.inMoney(in,money);
        }
    });
}
  • 测试类
/**
 - Created by Zhuang on 2018/4/23.
 - 转账案例的测试类
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1 {
    //测试业务层类
    @Resource(name = "accountService")
    private AccountService accountService;
    @Test
    public void demo1(){
        accountService.transfer("aaa","bbb",200d);
    }
}

五、声明式事务管理

  • 基于TransactionProxyFactoryBean的方式

    1. 配置事务管理器

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource"/>
      </bean>
    2. 配置业务层的代理

      <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          <!--配置目标对象-->
          <property name="target" ref="accountService"/>
          <!--注入事务管理器-->
          <property name="transactionManager" ref="transactionManager"/>
          <!--注入事务属性-->
          <property name="transactionAttributes" >
              <props>
                  <!--
                      prop的格式:
                         * PROPAGATION :事物的传播行为
                         * ISOLATION   :事务的隔离级别
                         * readOnly     :只读
                         * -Exception  :发生哪些异常回滚事务
                         * +Exception  :发生哪些异常事务不回滚
                  -->
                  <prop key="transfer">PROPAGATION_REQUIRED</prop>
              </props>
          </property>
      </bean>
    3. 测试类修改

    /**
     * Created by Zhuang on 2018/4/23.
     * Spring的声明式事务管理的方式一的测试类
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext2.xml")
    public class SpringDemo2 {
        /**
         * 注入代理类:因为代理类进行了增强的操作
         */

        //测试业务层类
        @Resource(name = "accountServiceProxy")
        //@Resource(name = "accountService")
        private AccountService accountService;
        @Test
        /**
         * 转账案例:
         */
        public void demo2(){
            accountService.transfer("aaa","bbb",200d);
        }

    }
  • 基于AspectJ的XML方式的配置

    1. 配置事务通知

      <tx:advice id="txAdvice" transaction-manager="transactionManager">
          <tx:attributes>
              <!--
                     * PROPAGATION        :事物的传播行为
                     * ISOLATION          :事务的隔离级别
                     * readOnly           :只读
                     * rollback-for       :发生哪些异常回滚事务
                     * no-rollback-for    :发生哪些异常事务不回滚
                     * timeout            :过期信息
              -->
              <tx:method name="transfer" propagation="REQUIRED"/>
          </tx:attributes>
      </tx:advice>
    2. 配置切面

      <aop:config>
          <!--配置切入点-->
          <aop:pointcut id="pointcut1" expression="execution(* cn.jxufe.spring.demo3.service.AccountService+.*(..))"/>
          <!--配置切面-->
          <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
      </aop:config>
    3. 测试类

    /**
     * Created by Zhuang on 2018/4/23.
     * Spring声明式事务管理的方式二:基于AspectJ的XML方式的配置
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext3.xml")
    public class SpringDemo3 {
        @Resource(name = "accountService")
        private AccountService accountService;
        @Test
        /**
         * 转账案例:
         */
        public void demo3(){
            accountService.transfer("aaa","bbb",200d);
        }
    }
  • 基于注解的事务管理的方式

    1. 配置事务管理器

      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource"/>
      </bean>
    2. 开启注解事务

      <tx:annotation-driven transaction-manager="transactionManager" />
    3. 业务层实现类

    /**
     * @Transactional注解中的属性
     * propagation        :事物的传播行为
     * isolation          :事务的隔离级别
     * readOnly           :只读
     * rollback-for       :发生哪些异常回滚事务
     * no-rollback-for    :发生哪些异常事务不回滚
     */
    @Transactional
    public class AccountServiceImpl implements AccountService {
        //注入DAO类
        private AccountDao accountDao;
    
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
    
        @Override
        public void transfer(String out,String in,Double money) {
            accountDao.outMoney(out,money);
            //异常:
            int i = 1 / 0;
            accountDao.inMoney(in,money);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值