六、声明事务
1.基于注解方式做事务处理
环境搭建:
1).导入相关依赖
* 数据源,数据库驱动、Spring-jdbc模块
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
2).配置数据源、JdbcTemplate(Spring提供简化数据源操作)操作数据源
@EnableTransactionManagement
@ComponentScan("com.it.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws Exception{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
//
@Bean
public JdbcTemplate jdbcTemplate() throws Exception{
//spring对@Configuration会特殊处理,给容器中加组件的方法多次调用都只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注册事务管理器
@Bean
public PlatformTransactionManager platformTransactionManager() throws Exception{
return new DataSourceTransactionManager(dataSource());
}
}
3).给方法标注上@Transactional 表示当前方法是一个事务方法
4).@EnableTransactionManagement开启基于注解的事务管理功能:
5).配置事务管理器来控制事务
- dao
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(){
String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?);";
String username = UUID.randomUUID().toString().substring(0, 5);
jdbcTemplate.update(sql,username,19);
}
}
- service
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional//不加事务,数据库就不会回滚,会添加一条记录
public void insertUser(){
userDao.insert();
//otherDao.other();
System.out.println("插入完成.....");
int i = 10/0;
}
}
- 测试
@Test
public void test01(){
//1.创建applicationContext
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = applicationContext.getBean(UserService.class);
userService.insertUser();
applicationContext.close();
}
- 效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PzeFMMWh-1582949331658)(C:\Users\单少宝宝\AppData\Roaming\Typora\typora-user-images\1582820209773.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tdDoFdnn-1582949331663)(C:\Users\单少宝宝\AppData\Roaming\Typora\typora-user-images\1582820226230.png)]
此时的数据库中并未添加新的记录,说明 我们的事务管理开始工作了。
2.@EnableTransactionManagement的实现原理:
1)、@EnableTransactionManagement
利用TransactionManagementConfigurationSelector给容器中导入组件。
导入两个组件
AutoProxyRegistrar、
ProxyTransactionManagementConfiguration
2)、AutoProxyRegistrar:
给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件
InfrastructureAdvisorAutoProxyCreator:?
利用重置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
3)、ProxyTransactionManagementConfiguration 做了什么?
1.给容器中注册事务增强器:
事务增强器要用事务注解 的信息,AnnotationTransactionAttributeSource来解析事务注解
2.事务拦截器:
TransactionInterceptor:保存了事务属性的信息,事务管理器;
他是一个MethodInterceptor:
在目标方法执行的时候:
执行拦截器链:
事务拦截器:
1)、先获取事务相关的属性
2)、再获取PlatformTransactionManager,如果事先没有添加指定任何
transactionmanager,最终会从容器中执照类型获取一个PlatformTransactionManager
3)、执行目标方法
如果异常,获取到事务管理器,利用事务管理器回滚操作:
如果正常,利用事务管理器,提交 事务
-
事务抽象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hAMqcgWu-1582949331665)(C:\Users\单少宝宝\AppData\Roaming\Typora\typora-user-images\1582868905052.png)]
-
事务拦截
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OVhC9kSN-1582949331666)(C:\Users\单少宝宝\AppData\Roaming\Typora\typora-user-images\1582869299757.png)]
大脑斧 发布了11 篇原创文章 · 获赞 18 · 访问量 4580 私信 关注