Spring的事务管理
-
编程式事务管理 : 使用spring提供的TransactionTemplate来实现事务管理
-
声明式事务管理 : 使用注解@Transactional ,利用AOP来实现事务管理
-
AOP的典型应用就是Spring的声明式事务管理.
-
编程式事务管理:
-
在TransactionTemplates中实现事务逻辑,事务本身的功能由TransactionTemplates完成.
-
导入依赖:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.1.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.1.RELEASE</version> </dependency>
-
配置类:
@Configuration //设置为配置类 @ComponentScan("com.li.spring") //指定包扫描 @PropertySource("database.properties") //读取配置文件 public class AopConfig { @Value("${jdbc.url}") private String url; @Value("${jdbc.driverClass}") private String driverClassName; @Value("${jdbc.userName}") private String userName; @Value("${jdbc.password}") private String password; //配置数据源=>提供connection pool @Bean public DruidDataSource druidDataSource(){ //得到一个druid连接池对象 DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); druidDataSource.setUsername(userName); druidDataSource.setPassword(password); return druidDataSource; } @Bean public QueryRunner queryRunner(){ return new QueryRunner(dataSourceProxy()); } //数据源的代理,spring能够去控制事务的打开和提交等操作 @Bean public TransactionAwareDataSourceProxy dataSourceProxy(){ return new TransactionAwareDataSourceProxy(druidDataSource()); } //事务管理器,管理事务,spring的统一的事务管理接口 //PlatformTransactionManager接口里面有三个方法: //getTransaction 得到事务 //commit 提交事务 //rollback 回滚事务 @Bean public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dataSourceProxy()); } //统一的事务管理模板,只依赖PlatformTransactionManager接口,可以放其他的实现类 @Bean public TransactionTemplate transactionTemplate(){ return new TransactionTemplate(transactionManager()); } // 事务模板 -> 事务管理器 ->数据源代理 ->数据源 }
-
业务层类:
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private QueryRunner queryRunner; @Autowired private TransactionTemplate transactionTemplate; @Override public void test() { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { try { queryRunner.update("insert into user values(default,?,?)","li1","99929"); if(transactionStatus!=null){ throw new RuntimeException("人工制造错误"); } queryRunner.update("delete from user where user_id=7"); queryRunner.update("update user set user_name=? where user_id=?","superli",3); } catch (SQLException e) { e.printStackTrace(); //出现异常,设置回滚 transactionStatus.setRollbackOnly(); } } }); } }
测试类:
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(AopConfig.class); UserService userService = acac.getBean("userService", UserService.class); userService.test(); } }
结果:
事务开启成功,数据都没有插入进去
-
-
声明式事务管理:
-
导入依赖,跟编程式事务管理导入相同的依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.2.1.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.1.RELEASE</version> </dependency>
配置类:与编程式事务管理不同是,声明式事务管理多了一个@EnableTransactionManagement的注解,用来开启事务,没有事务管理器和事务模板
@Configuration //设置为配置类 @ComponentScan("com.li.spring") //指定包扫描 @PropertySource("database.properties") //读取配置文件 @EnableTransactionManagement //启动事务管理 public class AopConfig2 { @Value("${jdbc.url}") private String url; @Value("${jdbc.driverClass}") private String driverClassName; @Value("${jdbc.userName}") private String userName; @Value("${jdbc.password}") private String password; //配置数据源 @Bean public DruidDataSource druidDataSource(){ //得到一个druid连接池对象 DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); druidDataSource.setUsername(userName); druidDataSource.setPassword(password); return druidDataSource; } @Bean public QueryRunner queryRunner(){ return new QueryRunner(dataSourceProxy()); } //数据源的代理,Spring能够去控制事务的打开和提交等操作 @Bean public TransactionAwareDataSourceProxy dataSourceProxy(){ return new TransactionAwareDataSourceProxy(druidDataSource()); } }
业务类:与编程式事务管理不同是直接使用@Transactional注解启动事务,在抛出异常时会自动进行事务回滚,方便了很多
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private QueryRunner queryRunner; @Transactional public void test2() throws SQLException{ queryRunner.update("insert into user values(default,?,?)","琪琪1","99929"); if(queryRunner!=null){ throw new RuntimeException("人造错误"); } queryRunner.update("delete from user where user_id=7"); queryRunner.update("update user set user_name=? where user_id=?","superli",3); } }
测试类:
public class App { public static void main(String[] args) { AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(AopConfig2.class); UserService userService = acac.getBean("userService", UserService.class); try { userService.test2(); } catch (SQLException e) { e.printStackTrace(); } } }
结果:
当然,数据也没有插入进去啦
-
声明式事务管理总结:
-
@Transactional
- 配置类加@EnableTransactionManagement,启动spring的事务管理机制
- 配置 datasource -> datasourceProxy -> PlatformTransactionManager + queryRunner
- 需要的方法上加@Transactional,开启事务,遇到异常会进行事务回滚
- AOP实现
- 切入点: @Transactional所在的方法
- 通知: Spring的事务管理
-