一、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 // jdbcTemplate27 @Bean28 public JdbcTemplate jdbcTemplate(){29 System.out.println("初始化 JdbcTemplate ");30 31 JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource());32 return jdbcTemplate;33 }34 35 // 事物管理器36 @Bean37 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 // @Override18 // public Object doInTransaction(TransactionStatus status) {19 // return null;20 // }21 // });22 }