Spring数据JPA和事务管理

时间:2018-09-20 11:48:22

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

在我的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。

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

我希望读取和写入操作都可以在单个事务中执行。如果我的理解是正确的,那么对服务方法 updateClientByIdAndKey 使用 @Transactional 会在我打算执行的两个事务中同时运行,还是会在一个事务中同时执行这两个操作? >

请让我知道我是否在这里丢失任何东西。

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

当您将@Transactional注释添加到updateClientByIdAndKey方法时,spring将仅创建一个读写事务(除非您使用以下命令在@Transactional方法上添加了额外的findByIdAndKey/save注释: PROPAGATION_REQUIRES_NEW或其他类型的propagation。当您将readOnly = true添加到@Transactional时,spring将会在休眠会话中设置flushModeNEVER 。这意味着您无法执行任何创建,更新,删除操作。

答案 2 :(得分:1)

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

@Transactional(readOnly = true)

方法 updateClientByIdAndKey 应该使用

@Transactional

updateClientByIdAndKey 中,除非您的嵌套方法 findByIdAndKey 定义了

,否则仅使用一个读写事务。
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)

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