spring开启事务

5 篇文章 0 订阅
4 篇文章 0 订阅

1 概述

我们通过A向B转账500元这个例子来讲解spring如何开启事务

2 环境准备

2.1 spring整合mybatis

spring整合mybatis

2.2 添加dao、service(在service方法中调用dao方法实现转账效果)

  1. 创建AccountDao接口
package cn.qiguai.dao;

import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

public interface AccountDao {
	@Update("update account set money = money - ${money} where id = ${id}")
	void reduceMoney(@Param("id") int id, @Param("money") int money);

	@Update("update account set money = money + ${money} where id = ${id}")
	void addMoney(@Param("id") int id, @Param("money") int money);
}
  1. 创建AccountService接口
package cn.qiguai.service;

public interface AccountService {
	void transfer();
}
  1. 创建AccountService接口的实现类AccountServiceImpl
package cn.qiguai.service.impl;

import cn.qiguai.dao.AccountDao;
import cn.qiguai.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AccountServiceImpl implements AccountService {
	@Autowired
	private AccountDao accountDao;

	@Override
	public void transfer() {
		//A向B转账
		accountDao.reduceMoney(1, 500);
		accountDao.addMoney(2, 500);
	}
}

2.3 数据库准备

test数据库中的account表数据如下
account表数据

3 不开启事务实现转账

3.1 创建测试类(Demo)

package cn.qiguai;

import cn.qiguai.config.SpringConfig;
import cn.qiguai.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Demo {
	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
		AccountService accountService = ac.getBean(AccountService.class);
		accountService.transfer();
	}
}

3.2 运行结果

运行结果如下,成功实现转账
运行结果

3.3 BUG

  1. 但是在转账的过程中并不是一帆风顺的,我们来模拟一个异常
  2. 在模拟之前,我们需要将数据库数据恢复
  3. AccountServiceImpl.transfer方法中添加一个异常
package cn.qiguai.service.impl;

import cn.qiguai.dao.AccountDao;
import cn.qiguai.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AccountServiceImpl implements AccountService {
	@Autowired
	private AccountDao accountDao;

	@Override
	public void transfer() {
		//A向B转账
		accountDao.reduceMoney(1, 500);
		
		//模拟异常
		int i = 1 / 0;
		
		accountDao.addMoney(2, 500);
	}
}
  1. 现在我们再次运行测试类,观察结果,我们发现账户1的钱少了,而账户2的钱并没有增加。原因是在账户1转账后发生了异常,账户2增加钱的代码没有被执行。这时候就需要开启事务,通过事务管理使用加钱和减钱同成功或同失败
    运行结果

4 开启事务实现转账

将数据库的数据恢复

4.1 使用Transactional注解开启事务

AccountService.transfer方法中使用注解开启事务

package cn.qiguai.service;

import org.springframework.transaction.annotation.Transactional;

public interface AccountService {
	@Transactional
	void transfer();
}

4.2 设置事务管理器(在JdbcConfig中)

在JdbcConfig中添加如下代码

@Bean
public PlatformTransactionManager transactionManager(DataSource ds) {
	DataSourceTransactionManager dstm = new DataSourceTransactionManager();
	
	dstm.setDataSource(ds);
	
	return dstm;
}

4.3 告诉spring使用注解开启了事务

在SpringConfig中添加EnableTransactionManagement注解

package cn.qiguai.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan("cn.qiguai")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MyBatisConfig.class})
@EnableTransactionManagement
public class SpringConfig {
}

4.4 运行测试类

观察运行结果,我们发现在发生异常后,A向B的转账并没有发生,达到预期效果
运行结果

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值