【问题标题】:Spring data JPA and transaction managementSpring数据JPA和事务管理
【发布时间】:2019-02-24 17:29:13
【问题描述】:

在我的 spring 服务中,我调用了两个 spring 数据存储库方法

@Service
public class ClientService {
    public void updateClientByIdAndKey(final Integer id, final String key) {
        final Client client = clientRepository.findByIdAndKey(id, key);
        // .. Update client details
        client.save(client);
   }
}

现在我的查询与事务管理有关。据我了解并看过代码,spring 存储库使用 @Transactional 为其方法启用了事务。对于选择操作,它具有 readonly=true。

我对事务的理解是,当执行选择操作时,会创建一个事务,然后为保存操作创建另一个事务,因为对于选择操作,事务是 readOnly=true。

我希望在单个事务中执行读取和写入操作。如果我上面的理解是正确的,那么在服务方法 updateClientByIdAndKey 上使用 @Transactional 将在一个事务中运行,这是我的意图,还是会在一个事务中执行两个操作? p>

如果我在这里遗漏了什么,请告诉我。

【问题讨论】:

标签: java spring transactions spring-data-jpa spring-transactions


【解决方案1】:

方法findByIdAndKey不需要做COMMIT(存储更改到数据库),应该注释为

@Transactional(readOnly = true)

方法updateClientByIdAndKey应该使用

@Transactional

updateClientByIdAndKey 中只使用一个读写事务,除非您的嵌套方法 findByIdAndKey 定义了一个

@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)

在这种情况下,您正在显式创建一个没有意义的新(只读)事务。

【讨论】:

    【解决方案2】:

    @Transactional 的 ReadOnly 属性默认为 false。通过简单地使用 Transactional 注释方法,读取/选择操作和更新操作都将在单个事务中发生。如果您将属性更改为 true,我猜您不会发生两个事务,而是会在尝试更新时引发异常。

    编辑: 如果该方法未使用 Transactional 注释,则两个操作都不会在单个事务中执行。事实上,根据您如何配置 ORM,执行更新时可能会引发异常,因为连接将在选择后关闭。

    【讨论】:

    • 感谢您的意见@Dean。但是如果我不使用@Transactional 注释服务方法,查询是否会在一个事务中在内部执行选择和更新操作?
    • 你在使用 Hibernate 吗?
    • 如果您不使用@Transactional 注释来注释服务方法,spring 将在没有任何事务的情况下执行这两个查询。所以数据会在save方法调用上持久化。
    【解决方案3】:

    当你在updateClientByIdAndKey 方法中添加@Transactional 注释时,spring 将只创建一个读写事务(除非你在findByIdAndKey/save 方法上使用PROPAGATION_REQUIRES_NEW 或其他类型的@ 添加额外的@Transactional 注释987654321@。当你将readOnly = true添加到@Transactional时,Spring会将Hibernate会话上的flushMode设置为NEVER。这意味着你不能执行任何创建、更新、删除操作。

    【讨论】:

      猜你喜欢
      • 2017-12-23
      • 2018-10-24
      • 2018-12-30
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多