目录
一、Spring事务简介
1、Spring事务作用
2、Spring事务案例
二、Spring事务角色
三、Spring事务相关配置
1、相关配置
2、案例
3、事务传播行为
一、Spring事务简介
1、Spring事务作用
事务作用:在数据层保障一系列的数据库操作同成功同失败
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
2、Spring事务案例
环境准备
Spring整合Mybatis相关代码(依赖、JdbcConfig、MybatisConfig、SpringConfig)省略
public interface AccountDao {
@Update("update tbl_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update tbl_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
}
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
public void transfer(String out,String in ,Double money) ;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(String out,String in ,Double money) {
accountDao.outMoney(out,money);
int i = 1/0;
accountDao.inMoney(in,money);
}
}
1、在业务层接口上添加Spring事务管理
public interface AccountService {
//配置当前接口方法具有事务
@Transactional
public void transfer(String out,String in ,Double money) ;
}
注意事项:
(1)Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合
(2)注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务
2、设置事务管理器(将事务管理器添加到IOC容器中)
说明:可以在JdbcConfig中配置事务管理器
//配置事务管理器,mybatis使用的是jdbc事务
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
注意事项:
(1)事务管理器要根据实现技术进行选择
(2)MyBatis框架使用的是JDBC事务
3、开启注解式事务驱动
@Configuration
@ComponentScan("com.csdn")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//开启注解式事务驱动
@EnableTransactionManagement
public class SpringConfig {
}
4、运行测试类,查看结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer() throws IOException {
accountService.transfer("Tom","Jerry",100D);
}
}
二、Spring事务角色
- 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
- 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法
三、Spring事务相关配置
1、相关配置
2、案例
(1)需求分析
需求:实现任意两个账户间转账操作,并对每次转账操作在数据库进行留痕
需求微缩:A账户减钱,B账户加钱,数据库记录日志
分析:
①:基于转账操作案例添加日志模块,实现数据库中记录日志
②:业务层转账操作(transfer),调用减钱、加钱与记录日志功能
实现效果预期:
无论转账操作是否成功,均进行转账操作的日志留痕
存在的问题:
日志的记录与转账操作隶属同一个事务,同成功同失败
实现效果预期改进:
无论转账操作是否成功,日志必须保留
(2)案例代码
环境准备
USE spring_db;
CREATE TABLE tbl_log(
id INT PRIMARY KEY AUTO_INCREMENT,
info VARCHAR(255),
createDate DATE
);
public interface LogService {
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional
void log(String out, String in, Double money);
}
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
public interface LogDao {
@Insert("insert into tbl_log (info,createDate) values(#{info},now())")
void log(String info);
}
1、在AccountServiceImpl中调用logService中添加日志的方法
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
public void transfer(String out,String in ,Double money) {
try{
accountDao.outMoney(out,money);
int i = 1/0;
accountDao.inMoney(in,money);
}finally {
logService.log(out,in,money);
}
}
}
2、在LogService的log()方法上设置事务的传播行为
public interface LogService {
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
void log(String out, String in, Double money);
}
3、运行测试类,查看结果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer() throws IOException {
accountService.transfer("Tom","Jerry",50D);
}
}
3、事务传播行为
事务传播行为:事务协调员对事务管理员所携带事务的处理态度