spring事务管理

86 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Spring事务管理

举个例子就是你要向别人转账,从你的银行卡扣100块钱到别人的银行卡,中间出现了异常,导致你的银行卡扣了100块钱,但是别人的银行卡的钱没增加。事务管理可以解决这种情况。

spring事务管理做的就是这么一件事:在数据层或业务层保障一系列的数据库同成功、同失败。


1. 前置工作

环境就用之前整合好的mybatis环境。

step1:mapper接口处理

public interface TblAccountMapper {
    // @Select("select * from tbl_account")
    List<TblAccount> selectAll();

    void inMoney(@Param("name") String name, @Param("money") Double money);
    void outMoney(@Param("name") String name, @Param("money") Double money);
}

该mapper对应的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.yldclass.dao.TblAccountMapper">
    <select id="selectAll" resultType="com.yldclass.pojo.TblAccount">
        select * from tbl_account;
    </select>
    <update id="inMoney">
        update tbl_account set money = money + #{money}
        where name = #{name};
    </update>
    <update id="outMoney">
        update tbl_account set money = money - #{money}
        where name = #{name};
    </update>
</mapper>

step2:写一下service层的接口和实现

public interface AccountService {
    /**
    * @Description: 转账的接口方法
    * @Param: [out, in, money]
     * @Param: out转出方
     * @Param: in 转入方
     * @Param: money转出转入金额
    */
    public void transfer(String out,String in,Double money);
}
@Component("AccountTransfer")
public class AccountServiceImpl implements AccountService{
    //要做一个自动装配注入进去
    @Autowired
    private TblAccountMapper accountDao;
    @Override
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out,money);
        //加入一个异常
        int i = 1/0;
        accountDao.inMoney(in,money);
    }
}

这里对应的实现写了一个异常。并且没有去做事务。

【注】这个类要放到spring容器中。

step3:写一个测试类:主要实现从liming的账户转钱到zhangsan的账户。

public class App {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        TblAccountMapper account = (TblAccountMapper) ctx.getBean("tblAccountMapper");
        AccountService transfer = (AccountService) ctx.getBean("AccountTransfer");
        transfer.transfer("liming","zhangsan",100.0);
        List<TblAccount> tblAccounts = account.selectAll();
        System.out.println(tblAccounts);
    }
}

测试结果如下:

liming转了100,但zhangsan没有收到。

2. 开启事务

step1:在业务层接口上添加spring的事务管理。

    @Transactional
    public void transfer(String out,String in,Double money);

【注意事项】

  1. Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合
  2. 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务

step2:设置事务管理器

   //配置事务管理器,mybatis使用的是jdbc事务
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dtm = new DataSourceTransactionManager();
        dtm.setDataSource(dataSource);
        return dtm;
    }

step3:@EnableTransactionManagement注解开启事务驱动

@EnableTransactionManagement
public class SpringConfig {
}

运行结果:

出现异常,数据不变。

事务角色