Spring事务控制
事务
什么是事务
在处理一件事情的时候,可能会涉及多个需要与数据库交互的操作,如果这件事中途出现问题,那么所有修改数据库的操作都应该撤回
这一件事情就是事务,我们希望处理一件事时,修改数据库的操作要么一起成功或者一起失败(也有可能部分一定要成功,如日志功能)
配置事务管理
说明
我们使用的DataSource是阿里云的Druid,使用的数据层访问框架是Mybatis,他们底层的事务控制都是JDBC,刚好Spring自带的事务控制也是使用的JDBC,所以不用导入新的坐标,直接往Spring容器中添加一个事务控制的实现类,然后使用它就行了。
创建事务管理的Bean
在org.example.config.JdbcConfig配置类中添加一个叫做PlatformTransactionManager平台事务管理器的Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| package org.example.config;
import com.alibaba.druid.pool.DruidDataSource; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
public class JdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password;
@Bean public DruidDataSource druidDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driver); druidDataSource.setUrl(url); druidDataSource.setUsername(username); druidDataSource.setPassword(password); return druidDataSource; }
@Bean public PlatformTransactionManager platformTransactionManager(DataSource dataSource) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); dataSourceTransactionManager.setDataSource(dataSource); return dataSourceTransactionManager; } }
|
配置事务
指定哪些服务是需要事务的,将注释加在接口上,实现类上都可以,方法上也行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| package org.example.service.impl;
import org.example.dao.UserDao; import org.example.domain.User; import org.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.util.List;
@Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao;
@Transactional public void transfer(Integer reference, Integer dest, Double money) { User user1 = userDao.findById(reference); user1.setBalance(user1.getBalance() - money); userDao.update(user1); int i = 1 / 0;
User user2 = userDao.findById(dest); user2.setBalance(user2.getBalance() + money); userDao.update(user2); } }
|
开启事务注解
在org.example.config.SpringConfig配置类中开启事务注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package org.example.config;
import org.springframework.context.annotation.*; import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@ComponentScan({"org.example.service","org.example.aop"})
@PropertySource({"classpath:jdbc.properties"})
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableAspectJAutoProxy
@EnableTransactionManagement public class SpringConfig { }
|
测试是否成功
编写测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| package org.example.service.impl;
import org.example.config.SpringConfig; import org.example.service.UserService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {SpringConfig.class}) public class UserServiceImplTest { @Autowired private UserService userService;
@Test public void testTransfer() { userService.transfer(1,2,50D); } }
|
如果运行后,数据库中数据没有发生变换表示配置成功
事务扩展使用
事务角色
- 事务管理员:发起事务方
- 事务协调员:加入事务方
事务有很多属性,可以百度一下,新手入门