当前位置: 首页 > 面试题库 >

Spring @Transactional - isolation, propagation

秦博延
2023-03-14
问题内容

有人可以通过实际示例解释注释中的隔离和传播参数@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例程时总是创建新事务,而在离开时总是在其中完成:

public class FooService {
    private Repository repo1;
    private Repository repo2;

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void provideService() {
        repo1.retrieveFoo();
        repo2.retrieveFoo();
    }
}

如果我们改为使用Required,则在进入例程时如果事务已经打开,则事务将保持打开状态。还要注意,a的结果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()它不会回滚,因为它创建了它自己的子事务。
  • Required:我们希望一切都回滚而后备存储保持不变。


 类似资料:
  • 问题内容: 我一直在尝试: 关于我的服务方式,但spring抱怨说: 我该如何解决? 问题答案: JPA不支持自定义隔离级别。你可以扩展类并覆盖与连接有关的方法,以便可以在 这是我写的但尚未测试的东西: 然后将其定义为你的属性

  • 问题内容: 以下是我的申请流程 控制器-服务-存储库 在服务层,我们具有注释。我们还具有配置,在其中指定实体管理器和txn管理器。 我的怀疑是我认为考虑了在其中指定的txn管理器,并且在服务层进行指定没有影响。例如:服务层可以映射到自定义的txn管理器,其中服务调用的存储库可能具有不同的txn管理器。在那种情况下会不会造成问题? 有人可以澄清一下,在使用jpa存储库时是否需要将其放置在服务层上?

  • 问题内容: 我在Web应用程序中使用 Spring 3.1 + Hibernate4.x 。在我的DAO中,我将用户类型对象保存如下 但是出现以下异常: 我用谷歌搜索并找到了类似的问题,有以下解决方案: 那解决了问题。但是在该解决方案中,手动开始和提交事务有很多麻烦。 没有手动开始/提交交易,我不能直接使用 吗? 我也尝试在服务/ dao方法上使用,但是问题仍然存在。 编辑: 这是我的Spring

  • 但获得以下异常: 我搜索了一下,在SO上找到了类似的问题,解决方法如下: 这就解决了问题。但在该解决方案中,手动开始和提交事务会有很多麻烦。 请帮帮忙。

  • 我之前有一个关于这个问题的帖子已经解决了。然而,自从用自动连线bean和较少的XML配置重建项目后,我发现我正在重新考虑这个问题。我遵循了我以前的项目实现这一点的方式,但它不起作用。有人能帮助我为什么或者我应该改变什么来使它工作吗? 注册服务: 注册DAO:

  • 我有如下代码 ProcessTransactionInterral引发扩展RuntimeException的ServiceUnAvailableException 但是尽管有rollbackFor=exception.class,事务却没有回滚。你能帮帮我吗。