1. SpringBoot-声明式事务
1.1 依赖
数据源、数据库驱动、Spring-jdbc模块
<dependencies>
<!-- IOC依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!-- AOP依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!--spring操作数据库模块,用jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
<!--spring操作数据库模块,用hibernate-->
<!-- <dependency>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring-orm</artifactId>-->
<!-- <version>4.3.12.RELEASE</version>-->
<!-- </dependency>-->
<!-- 数据源-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
</dependencies>
1.2
- 2.配置数据源,JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
- 3.给方法上标注@Transactional 表示当前方法是一个事务方法
- 4.@EnableTransactionManagement 开启基于注解的事务管理功能
@EnableXXX
- 5.配置事务管理器来控制事务
@Bean
public PlatformTransactionManager transactionManager()
1.3 代码
- 配置类:
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 声明式事务:
*
* 环境搭建:
* 1、导入相关依赖
* 数据源、数据库驱动、Spring-jdbc模块
* 2、配置数据源,JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
* 3、给方法上标注@Transactional 表示当前方法是一个事务方法
* 4、@EnableTransactionManagement 开启基于注解的事务管理功能
* @EnableXXX
* 5、配置事务管理器来控制事务
* @Bean
* public PlatformTransactionManager transactionManager()
*
*/
@EnableTransactionManagement
@ComponentScan("com.fcc.springAnnotation.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://192.168.1.91:3306/test");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception {
//Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
return new DataSourceTransactionManager(dataSource());
}
}
- Dao 类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.UUID;
@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类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void insertUser(){
userDao.insert();
//otherDao.other()...
System.out.println("插入完成。。。");
int i =1/0;
}
}
- 测试类:
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestTx {
@Test
public void test01(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean(UserService.class);
userService.insertUser();
context.close();
}
}
2. 底层原理
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
/**
* 声明式事务:
*
* 环境搭建:
* 1、导入相关依赖
* 数据源、数据库驱动、Spring-jdbc模块
* 2、配置数据源,JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
* 3、给方法上标注@Transactional 表示当前方法是一个事务方法
* 4、@EnableTransactionManagement 开启基于注解的事务管理功能
* @EnableXXX
* 5、配置事务管理器来控制事务
* @Bean
* public PlatformTransactionManager transactionManager()
*
*
*
* 原理:
* 1)、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector给容器中会导入
* 导入两个组件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2)、AutoProxyRegistrar:
* 给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行
* 3)、ProxyTransactionManagementConfiguration 做了什么?
* 1、给容器中注册事务增强器
* 1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
* 2)、事务拦截器:
* TransactionInterceptor;保存了事务属性信息,事务管理器
* 他是一个MethodInterceptor
* 在目标方法执行的时候;
* 执行拦截器链;
* 事务拦截器:
* 1)、先获取事务相关的属性
* 2)、在获取 PlatformTransactionManager,如果事先没有添加指定任何TransactionManager
* 最终会从容器中按照类型获取一个PlatformTransactionManager
* 3)、执行目标方法
* 如果异常,获取到事务管理器,利用事务管理器回滚事务
* 如果正常,利用事务管理器,提交事务
*
*
*
*/
@EnableTransactionManagement
@ComponentScan("com.fcc.springAnnotation.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://192.168.1.91:3306/test");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception {
//Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
return new DataSourceTransactionManager(dataSource());
}
}
- 总结
* 原理:
* 1)、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector给容器中会导入
* 导入两个组件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2)、AutoProxyRegistrar:
* 给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行
* 3)、ProxyTransactionManagementConfiguration 做了什么?
* 1、给容器中注册事务增强器
* 1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
* 2)、事务拦截器:
* TransactionInterceptor;保存了事务属性信息,事务管理器
* 他是一个MethodInterceptor
* 在目标方法执行的时候;
* 执行拦截器链;
* 事务拦截器:
* 1)、先获取事务相关的属性
* 2)、在获取 PlatformTransactionManager,如果事先没有添加指定任何TransactionManager
* 最终会从容器中按照类型获取一个PlatformTransactionManager
* 3)、执行目标方法
* 如果异常,获取到事务管理器,利用事务管理器回滚事务
* 如果正常,利用事务管理器,提交事务