有人可以通过实际示例解释注释中的隔离和传播参数@Transactional吗?
@Transactional
基本上,何时和为什么我应该选择更改其默认值。
好的问题,尽管不是一个简单的答案。
Propagation
定义事务之间的关系。常用选项:
Required
Requires_new
Isolation
定义事务之间的数据契约。
Read Uncommitted
Read Committed
Repeatable Read
Serializable
在多线程应用程序中,不同的级别具有不同的性能特征。我认为,如果你了解dirty reads概念,便可以选择一个不错的选择。
何时发生脏读的示例:
thread 1 thread 2 | | write(x) | | | | read(x) | | rollback | v v value (x) is now dirty (incorrect)
因此,可以设置一个合理的默认值(如果可以要求的话)Read Committed,它只能让你读取传播级别为的其他正在运行的事务已提交的值Required。然后,如果你的应用程序有其他需求,则可以从那里开始工作。
一个实际的例子,说明在进入provideService例程时总是创建新事务,而在离开时总是在其中完成:
provideService
public class FooService { private Repository repo1; private Repository repo2; @Transactional(propagation=Propagation.REQUIRES_NEW) public void provideService() { repo1.retrieveFoo(); repo2.retrieveFoo(); } }
如果我们改为使用Required,则在进入例程时如果事务已经打开,则事务将保持打开状态。还要注意,a的结果rollback可能会有所不同,因为多次执行可能会参与同一事务。
rollback
我们可以通过测试轻松验证行为,并查看结果随传播级别的不同:
@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 ... }
传播水平为
Requires new
fooService.provideService()