【问题标题】:Jpa, SpringData Concurrency issueJpa, SpringData 并发问题
【发布时间】:2018-08-30 21:42:13
【问题描述】:

我有两个端点用于编辑同一个实体 (Foo),一个用于属性 A,第二个用于属性 B。

/api/v2/foo/{foo_id}/a/{value}

/api/v2/foo/{foo_id}/b/{值}

@Entity
Class Foo {

  // id, properties

  @OneToOne
  private Bar bar;
}

和嵌套类

@Entity
Class Bar {
  private String a;
  private String b;
}

此端点在实体 Foo 的服务中进行并发操作

@Service
public class FooService{
  @Autowired
  private FooRepository fooRepository;

  void updateA(ADto adto){
    Foo tmp = fooRepository.findById(adto.getId());
    doLogic...
    fooRepository.saveAndFlush(tmp);
  }

  void updateB(BDto bdto){
    Foo tmp = fooRepository.findById(bdto.getId());
    doLogic...
    fooRepository.saveAndFlush(tmp);
  }
}

这两个调用是并发的,我的数据已损坏。 试图放入 Foo 实体

@Version
private Integer version;

尝试保存第二次通话时出现异常。 我想要实现的目标是当我保存域时,如果保存因并发失败以刷新最新版本并保存更改。

谁能给我一些建议???

【问题讨论】:

  • “这不是 Spring Data 造成的。控制的方法是在 JPA 和数据库领域。我建议你阅读 JPA 的乐观锁定以及数据库中的唯一索引。” ——奥利弗·吉尔克

标签: hibernate jpa concurrency spring-data aop


【解决方案1】:

如果您想更新不同的字段,也许您应该尝试使用@DynamicUpdate。

【讨论】:

    【解决方案2】:

    避免并发请求导致数据损坏的方法是使用数据库事务。

    发布的代码没有显示任何东西来表明您的交易边界在哪里。也许交易在您的存储库中?也许你打开了自动提交?无论如何,您需要在服务层中实现事务处理。

    • 将@Transactional 添加到服务类。检查这是 spring 注释而不是 javax 注释。

    • 检查您的 JPA 提供程序的配置以确保自动提交已关闭。

    • 检查您的版本字段是否映射到数据库列。

    【讨论】:

      猜你喜欢
      • 2015-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 2016-09-12
      • 2017-11-21
      • 2017-10-20
      相关资源
      最近更新 更多