参考资料:
[1]. 精通Spring4.X
[2]. 事务传播行为Requires new和Required的例子
[3]. 秒杀系统学习
事务传播行为
事务传播行为控制当前事务如何传播到被嵌套调用的目标服务接口方法中。
一个A方法(A事务)嵌套调用另外一个B方法(B事务),这个时候B事务的行为。
事务传播行为与隔离级别的关旭
事务传播行为是两个嵌套事务之间的关系。
隔离级别是两个并行的事务之间的关系,也就是没有什么关系,并行事务可能会出现脏写,脏读,不可重复读,幻读等问题,为了防止部分这些问题出现及平衡效率的问题,隔离级别又分为以下几个等级,uncommitted read, committed read, repeatable read, serializable。
事务传播行为例子(参考[2])
下面的代码中新建了一个事务,然后调用了fooService.provideService();
,
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:/fooService.xml")
public class FooServiceTests {
private @Autowired TransactionManager transactionManager;
private @Autowired FooService fooService;
@Test
public void testProvideService() {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
fooService.provideService();
transactionManager.rollback(status);
// assert repository values are unchanged ...
}
我们看到provideService中也有例外一个事务,这个时候问题就来了,两个事务之间怎么协商?
public class FooService {
private Repository repo1;
private Repository repo2;
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void provideService() {
repo1.retrieveFoo();
repo2.retrieveFoo();
}
}
我们看到上面标注了事务传播行为类型为Propagation.REQUIRES_NEW
,这意味着会新建一个事务,当外面的事务rollback的时候,不会影响这个事务,就好像里面的这个事务没有发生过一样(需要这种操作的场景一般在整个大事务中有小事务不需要rollback,见[3]里面的章节——订单号信息)。如果改为Required,则在这种外面的事务已经有的情况下,里面的事务加入到外面的事务。
编程式事务和声明式事务
编程式事务:用TransactionTemplate,需要写带入将DAO操作放到事务环境中。
声明式事务:使用XML或者注解配置即可,对代码的侵入性小,通过AOP实现。
网友评论