一、Spring事务管理实现方式
按是否通过编程分为声明式事务和编程式事务
-
声明式事务:
声明式事务:通过AOP(面向切面)方式在方法前使用编程式事务的方法开启事务,在方法后提交或回滚。用配置文件的方法或@(如:@Transactional)控制事务。
通过XML配置或者注解实现。
-
编程式事务:
手动开启、提交、回滚事务。
通过编程代码在业务逻辑时需要时自行实现,粒度更小。
二、声明式事务
本例通过@Transactional注解的方式实现声明式事务
1、ITargetService接口
1 public interface ITargetService { 2 3 void update(); 4 5 }
2、TargetService实现类
1 @Service 2 public class TargetService implements ITargetService { 3 4 @Autowired 5 JdbcTemplate jdbcTemplate; 6 7 @Transactional 8 @Override 9 public void update(){ 10 11 String sql="update user set name = '王四' where id = 3"; 12 int update = jdbcTemplate.update(sql); 13 } 14 }
3、配置类,主要是注入了数据源、JDBCTemplate 和 事务管理器
1 @Configuration 2 // 开启事务管理 3 @EnableTransactionManagement 4 @ComponentScan("com.test.tx.service") 5 public class MainConfig { 6 7 // 数据源 8 @Bean("druidDataSource") 9 public DataSource druidDataSource(){ 10 System.out.println("初始化数据源 DruidDataSource "); 11 12 String url="jdbc:mysql://192.168.0.1:3306/test?allowPublicKeyRetrieval=true&useSSL=true"; 13 String username = "root"; 14 String password = "123456"; 15 String driverClassName = "com.mysql.cj.jdbc.Driver"; 16 17 DruidDataSource druidDataSource = new DruidDataSource(); 18 druidDataSource.setUsername(username); 19 druidDataSource.setPassword(password); 20 druidDataSource.setUrl(url); 21 druidDataSource.setDriverClassName(driverClassName); 22 23 return druidDataSource; 24 } 25 26 // jdbcTemplate 27 @Bean 28 public JdbcTemplate jdbcTemplate(){ 29 System.out.println("初始化 JdbcTemplate "); 30 31 JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource()); 32 return jdbcTemplate; 33 } 34 35 // 事物管理器 36 @Bean 37 public TransactionManager transactionManager(){ 38 return new DataSourceTransactionManager(druidDataSource()); 39 } 40 }
4、主方法调用
1 public class MainStarter { 2 public static void main(String[] args) { 3 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class); 4 5 ITargetService targetService = context.getBean(ITargetService.class); 6 targetService.update(); 7 } 8 }
三、编程式事务
1、方法一:使用DefaultTransactionDefinition,定义一个事务,获取事务状态TransactionStatus,使用 PlatformTransactionManager 平台事务对象来管理
新建一个TestService
1 @Service 2 public class TestService { 3 4 @Autowired 5 private TransactionManager transactionManager; 6 7 @Autowired 8 private JdbcTemplate jdbcTemplate; 9 10 public void test1() { 11 PlatformTransactionManager txManager = (PlatformTransactionManager) this.transactionManager; 12 // 定义事务隔离级别,传播行为, 13 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 14 def.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ); 15 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 16 // 事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取; 17 // 获取事务状态后,Spring根据传播行为来决定如何开启事务 18 TransactionStatus status = txManager.getTransaction(def); 19 try { 20 jdbcTemplate.update("update user set name = '王五' where id = 3"); 21 int n = 1/0; 22 // 提交status中绑定的事务 23 txManager.commit(status); 24 } catch (RuntimeException e) { 25 // 回滚status中绑定的事务 26 txManager.rollback(status); 27 } 28 } 29 }
2、方式二:使用TransactionTemplate,该类继承了接口DefaultTransactionDefinition,用于简化事务管理,事务管理由模板类定义,主要是通过TransactionCallback回调接口或TransactionCallbackWithoutResult回调接口指定,通过调用模板类的参数类型为TransactionCallback或TransactionCallbackWithoutResult的execute方法来自动享受事务管理。
TransactionTemplate模板类使用的回调接口:
-
TransactionCallback:通过实现该接口的“T doInTransaction(TransactionStatus status) ”方法来定义需要事务管理的操作代码;
-
TransactionCallbackWithoutResult:继承TransactionCallback接口,提供“void doInTransactionWithoutResult(TransactionStatus status)”便利接口用于方便那些不需要返回值的事务操作代码。
1)配置类中添加TransactionTemplate 事务模版的注册
1 // 事务模版 2 @Bean 3 public TransactionTemplate transactionTemplate(){ 4 // DataSourceTransactionManager 实现了 PlatformTransactionManager 接口 5 TransactionTemplate template = new TransactionTemplate((PlatformTransactionManager)transactionManager() ); 6 // 设置隔离级别,重复读取 7 template.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ); 8 // 设置传播行为,重复读取 9 template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 10 return template; 11 }
2)使用事务模版 transactionTemplate
1 public void test2() { 2 3 transactionTemplate.execute(new TransactionCallbackWithoutResult() { 4 // 在事务中执行,且没有结果返回 5 @Override 6 protected void doInTransactionWithoutResult(TransactionStatus status) { 7 // 报异常,自动回滚,TransactionTemplate自动管理事务 8 jdbcTemplate.update("update user set name = '王五' where id = 3"); 9 throw new RuntimeException(); 10 } 11 } 12 ); 13 14 // 有结果返回的执行 15 // Object result = transactionTemplate.execute(new TransactionCallback<Object>() { 16 // // 在事务中执行 17 // @Override 18 // public Object doInTransaction(TransactionStatus status) { 19 // return null; 20 // } 21 // }); 22 }
参考:https://blog.csdn.net/liaohaojian/article/details/70139151