(十一)Spring 事务 - JdbcTemplate
1. 声明式事务和编程式事务
beginTransaction();
...
commmit();
...
rollback();
...
connection.autoCommit(false);
...
connection.commit();
而Spring的AOP将事务管理作为一个横切点进行模块化,很好的实现了声明式事务
2. @Transaction事务注解
- 写在方法上,只在当前方法有效
- 写在类上,当前类所有的方法都会使用事务
- 如果类和方法同时存在@Transaction,以方法层为准
- 标记在方法层上,事务管理控制力度更细,建议放在业务逻辑层,因为业务逻辑层存在嵌套调用
3. 事务属性
3.1 isolation - 事务隔离级别
用于处理事务并发所产生的问题
事务隔离级别 | 脏读 | 可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
-
读未提交(READ_UNCOMMITTED)
-
读已提交(READ_COMMITTED)
-
可重复读(REPEATABLE_READ)
-
序列化(SERIALIZABLE)
3.2 propagation - 事务传播行为
事务传播类型 | 外部不存在事务 | 外部存在事务 | |
---|---|---|---|
REQUIRED(默认) | 开启新的事务 | 融合到外部事务 | 适用增删改查 |
SUPPORTS | 不开启新的事务 | 融合到外部事务 | 适用查询 |
REQUIRES_NEW | 开启新的事务 | 挂起外部事务,开启新事务 | 适用外部事务和内部事务不相关 |
NOT_SUPPORTED | 不开启新的事务 | 挂起外部事务 | 不常用 |
MANDATORY | 抛出异常 | 融合到外部事务 | 不常用 |
NEWSTED | 开启新的事务 | 开启新事务为外部事务的子事务 | |
NEVER | 不开启新的事务 | 抛出异常 | 不常用 |
-
REQUIRED
@Transactional(propagation = Propagation.REQUIRED) public void methodA() { methodB(); // do something } @Transactional(propagation = Propagation.REQUIRED) public void methodB() { // do something }
-
SUPPORTS
@Transactional(propagation = Propagation.REQUIRED) public void methodA() { methodB(); // do something } // 事务属性为SUPPORTS @Transactional(propagation = Propagation.SUPPORTS) public void methodB() { // do something }
-
REQUIRES_NEW
@Transactional(propagation = Propagation.REQUIRED) public void methodA() { doSomeThingA(); methodB(); doSomeThingB(); // do something else } // 事务属性为REQUIRES_NEW @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodB() { // do something }
{ TransactionManager tm = null; try{ //获得一个JTA事务管理器 tm = getTransactionManager(); tm.begin();//开启一个新的事务 Transaction ts1 = tm.getTransaction(); doSomeThing(); tm.suspend();//挂起当前事务 try{ tm.begin();//重新开启第二个事务 Transaction ts2 = tm.getTransaction(); methodB(); ts2.commit();//提交第二个事务 } Catch(RunTimeException ex) { ts2.rollback();//回滚第二个事务 } finally { //释放资源 } //methodB执行完后,恢复第一个事务 tm.resume(ts1); doSomeThingB(); ts1.commit();//提交第一个事务 } catch(RunTimeException ex) { ts1.rollback();//回滚第一个事务 } finally { //释放资源 } }
-
NEWSTED
@Transactional(propagation = Propagation.REQUIRED) methodA(){ doSomeThingA(); methodB(); doSomeThingB(); } @Transactional(propagation = Propagation.NEWSTED) methodB(){ …… }
{ Connection con = null; Savepoint savepoint = null; try{ con = getConnection(); con.setAutoCommit(false); doSomeThingA(); savepoint = con2.setSavepoint(); try{ methodB(); } catch(RuntimeException ex) { con.rollback(savepoint); } finally { //释放资源 } doSomeThingB(); con.commit(); } catch(RuntimeException ex) { con.rollback(); } finally { //释放资源 } }
-
REQUIRED,REQUIRES_NEW,NESTED异同
3.3 timeout - 超时属性
3.4 readOnly - 事务只读
3.5 异常属性设置
- noRollbackFor - 异常不回滚
- rollbackFor - 异常回滚
- 默认对于RuntimeException 及其子类 采用的是回滚的策略;默认对于Exception 及其子类 采用的是提交的策略
4. 实战使用
- 如果当前业务方法是一组 增、改、删 可以这样设置事务 @Transactional
- 如果当前业务方法是一组 查询 可以这样设置事务 @Transactionl(readOnly=true)
- 如果当前业务方法是单个 查询 可以这样设置事务 @Transactionl(propagation=propagation.SUPPORTS ,readOnly=true)