微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 JPA 的乐观锁定休眠

如何解决使用 JPA 的乐观锁定休眠

JPA 乐观锁定不会在我期望的地方抛出 OptimisticLockException/StaleStateException。

这是我的设置: 我正在使用带有弹簧数据包的弹簧靴。所以我的存储库是版本化的,这不应该影响乐观锁定行为。在我的实体中,属性版本 (Long) 用 @Version 注释。我的应用程序由 3 层组成:

  • 持久层
  • 业务层
  • 传输层

为了在层之间映射对象,我使用了 mapstruct。

当传输层的控制器收到请求时,JSON-Payload 被映射到一个业务层对象来处理业务规则。版本始终映射到整个生命周期。 当我到达持久层时,我使用对象的 ID 在我的数据库中找到相应的实体。我的保存方法的签名如下所示:

@Transactional
public Entity saveEntity(BOEntity boEntity){
 Entity e = entityRepository.findById(boEntity.getId());
 entityMapper.updateEntity(boEntity,e);
 entityRepository.save(e);
}

当我的客户端加载相同的实体时,(例如两个浏览器选项卡)它们每个都具有相同版本的实体。在两个客户端中进行更改并保存。 版本包含在 boEntity 对象中并映射到实体中。 由于 findById 调用,实体被管理。 entitymanager 将尝试合并实体,并在两个请求中都成功。

合并第一个请求的实体的状态(与版本1)。 Hibernate 调用 executeUpdate 方法并写入数据库。版本增加到2。 现在,第二个请求以版本 1 的形式交付处于前一状态的实体。调用 save-method 并从持久性上下文中检索实体。它有版本 2,它被版本 1 的 boEntity 对象覆盖。

当 entityManager 现在合并实体时,不会抛出异常。 我的期望是由于旧版本而失败的第二个请求。 不是可以覆盖实体的版本吗?

我已经阅读了很多博客文章,但找不到任何提示

解决方法

默认的 JPA 乐观锁定机制仅在托管对象被刷新但在此期间被更改时才起作用。你想要的东西必须手动编码。只需将逻辑添加到您的 saveEntity 方法中:

@Transactional
public Entity saveEntity(BOEntity boEntity){
 Entity e = entityRepository.findById(boEntity.getId());
 if (boEntity.getVersion() != e.getVersion()) {
  throw new OptimisticLockException();
 }
 entityMapper.updateEntity(boEntity,e);
 entityRepository.save(e);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。