文章目录
- 1 概述
- 2 环境准备
- 2.1 spring整合mybatis
- 2.2 添加dao、service(在service方法中调用dao方法实现转账效果)
- 2.3 数据库准备
- 3 不开启事务实现转账
- 3.1 创建测试类(Demo)
- 3.2 运行结果
- 3.3 BUG
- 4 开启事务实现转账
- 4.1 使用`Transactional`注解开启事务
- 4.2 设置事务管理器(在JdbcConfig中)
- 4.3 告诉spring使用注解开启了事务
- 4.4 运行测试类
1 概述
我们通过A向B转账500元这个例子来讲解spring如何开启事务
2 环境准备
2.1 spring整合mybatis
spring整合mybatis
2.2 添加dao、service(在service方法中调用dao方法实现转账效果)
- 创建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);
}
- 创建AccountService接口
package cn.qiguai.service;
public interface AccountService {
void transfer();
}
- 创建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() {
accountDao.reduceMoney(1, 500);
accountDao.addMoney(2, 500);
}
}
2.3 数据库准备
test数据库中的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
- 但是在转账的过程中并不是一帆风顺的,我们来模拟一个异常
- 在模拟之前,我们需要将数据库数据恢复
- 在
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() {
accountDao.reduceMoney(1, 500);
int i = 1 / 0;
accountDao.addMoney(2, 500);
}
}
- 现在我们再次运行测试类,观察结果,我们发现账户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的转账并没有发生,达到预期效果
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)