Spring 数据 JPA 和事务管理

Spring data JPA and transaction management

在我的 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 为其方法启用了事务。对于 select 操作,它具有 readonly=true。

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

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

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

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

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

之后关闭

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

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

@Transactional(readOnly = true)

方法updateClientByIdAndKey应该使用

@Transactional

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

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

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