Spring声明式事务

134 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

事务回顾

事务的概念

​ 保证一组数据库的操作,要么同时成功,要么同时失败

四大特性

  • 隔离性

    多个事务之间要相互隔离,不能互相干扰

  • 原子性

    指事务是一个不可分割的整体,类似一个不可分割的原子

  • 一致性

    保障事务前后这组数据的状态是一致的。要么都是成功的,要么都是失败的。

  • 持久性

    指事务一旦被提交,这组操作修改的数据就真的的发生变化了。即使接下来数据库故障也不应该对其有影响。

3.2 实现声明式事务

​ 如果我们自己去对事务进行控制的话我们就需要值原来核心代码的基础上加上事务控制相关的代码。而在我们的实际开发中这种事务控制的操作也是非常常见的。所以Spring提供了声明式事务的方式让我们去控制事务。

​ 只要简单的加个注解(或者是xml配置)就可以实现事务控制,不需要事务控制的时候只需要去掉相应的注解即可。

案例环境准备

①数据初始化

CREATE DATABASE /*!32312 IF NOT EXISTS*/`spring_db` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `spring_db`;
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) DEFAULT NULL,
  `money` DOUBLE DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT  INTO `account`(`id`,`name`,`money`) VALUES (1,'三更',100),(2,'草堂',100);

②Spring整合Mybatis(参考上篇)

③创建Service和Dao

public interface AccountService {    
    /**    
* 转账     
* @param outId 转出账户的id     
* @param inId 转出账户的id     
* @param money 转账金额     */   
    public void transfer(Integer outId,Integer inId,Double money);}
@Servicepublic
class AccountServiceImpl implements AccountService {    
    @Autowired    
    private AccoutDao accoutDao;    
    public void transfer(Integer outId, Integer inId, Double money) {       
        //增加        
        accoutDao.updateMoney(inId,money);        
        //减少        
        accoutDao.updateMoney(outId,-money);    }}
public interface AccoutDao {    
    void updateMoney(@Param("id") Integer id,@Param("updateMoney") Double updateMoney);
}

AccoutDao.xml如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.springstudy.dao.AccoutDao"> 
    <update id="updateMoney">        
        update  account set money = money + #{updateMoney} where id = #{id} 
    </update></mapper>

注解实现

①配置事务管理器和事务注解驱动

在spring的配置文件中添加如下配置:

    <!--把事务管理器注入Spring容器,需要配置一个连接池-->  
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
<property name="dataSource" ref="dataSource"/>  
</bean> 
<!--开启事务注解驱动,配置使用的事务管理器-->
<tx:annotation-driven transaction-manager="txManager"/>
②添加注解

在需要进行事务控制的方法或者类上添加 @Transactional 注解就可以实现事务控制。

    @Transactional    
public void transfer(Integer outId, Integer inId, Double money) {   
    //增加        accoutDao.updateMoney(inId,money);
    //        System.out.println(1/0);        
    //减少        accoutDao.updateMoney(outId,-money);    }

注意:如果加在类上,这个类的所有方法都会受事务控制,如果加在方法上,就是那一个方法受事务控制。

注意,因为声明式事务底层是通过AOP实现的,所以最好把AOP相关依赖都加上。

       <dependency>  
       <groupId>org.aspectj</groupId>  
       <artifactId>aspectjweaver</artifactId>     
       <version>1.9.6</version>
       </dependency>