【发布时间】:2021-09-27 18:32:48
【问题描述】:
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 交付之前状态的实体。调用保存方法并从持久性上下文中检索实体。它具有版本 2,被版本 1 的 boEntity 对象覆盖。
当 entityManager 现在合并实体时,不会抛出异常。 我的期望是由于旧版本而失败的第二个请求。 不可以覆盖实体的版本吗?
我已经阅读了很多博客文章,但找不到任何提示。
【问题讨论】:
-
"不能覆盖实体的版本吗?"它不适用于programmer to touch。
-
如何加载你传入 save 方法的
BOEntity boEntity? -
BOEntity 来自请求的有效负载。首先,我有一个传输对象 (DTO),它映射到 BOEntity(包括版本)。 BOEntity 通过 mapstruct 写入到真实的 Entity 中。同样,版本被映射到先前加载的实体(因此实体的版本被覆盖)。假设我的 BOEntity 是我的 DTO(为简单起见)。不是正确的方法,通过 findById 从数据库中加载实体,然后通过设置它的字段来更新实体吗?版本 2 会被旧版本覆盖,Hibernate 会抛出异常?
-
当我创建一个具有与我想要更新的实体相对应的 ID 的新实体时,我得到了异常。实体然后处于非托管状态。当我调用 save 方法时,抛出异常。
标签: java hibernate jpa spring-data-jpa optimistic-locking