使用版本属性对实体进行乐观锁定可以很好地实现,并且易于实现:
<version property="VERSION" type="int" column="EX_VERSION" />
实体具有以下类型的属性:
private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }
到目前为止,一切都很好。现在,服务方法返回上述实体的数据传输对象(DTO),视图以HTML形式显示。对于更新页面,VERSION属性存储在HTML隐藏字段中,并与表单一起提交。
目的是使用version属性来确保如果显示的信息带有旧版本,则用户的更新将失败。
控制器通过调用包含更新信息(包括版本属性)的DTO的服务方法来响应用户更新请求,然后该服务方法使用数据访问对象(DAO)来保存更改:
public void update(SimpleDTO dto) {
SimplyEntity entity = getSimpleDao().load(dto.getId());
copyProperties(dto, entity); // all properties, including VERSION copied to entity
getSimpleDao().update(entity);
}
问题是Hibernate不尊重通过copyProperties(…)复制到实体中的version属性。我在以下论坛中找到了原因:https://forum.hibernate.org/viewtopic.php?f
= 1&t = 955893&p =
2418068
简而言之,当调用load()时,Hibernate将version属性缓存在会话缓存中,随后将其值更改为什么都无关紧要。我同意这是正确的行为,但Bosses指示我通过HTML表单属性传递版本(如果对此有更好的模式,我很乐意听到)。
我现在正在探索的一种解决方案是在更新发生之前使用hibernateTemplate.evict(simpleEntity)设置实体的版本后,将其从会话中退出。我希望这能奏效,但似乎效率不高。
我想请Hibernate检查实例本身的version属性,而不是仅从会话缓存中检查。
预先感谢您的答复!
-LES
您 真的 需要使用DTO吗?如果要传递实际的实体,就不会有这个问题-也不必再次加载该实体,这对性能而言并不是很好。
但是,即使您确实有使用DTO的正当理由,我也不太了解为什么要在保存之前尝试在 新近重新加载的 实体上更新版本号。考虑工作流中可能的不同方案:
您现在有两种可能性:
我有一个带有和的微服务。我使用注释对中的表执行操作。我遇到的问题是保存操作花费了太多的时间,所以我希望读取操作不被它阻塞。注意,保存是通过持久化实体来执行的。 当前,在所有并发保存操作完成之前,所有读取操作都不会返回结果,这意味着表被锁定。相反,我希望实现乐观锁定。我怎样才能做到呢?
问题内容: 我对Hibernate和Spring完全陌生,在尝试学习Spring,Hibernate,Maven等时,我只知道如何使用这三个方法来运行helloworld示例。根据我的基本理解,我被分配了执行乐观锁定的任务。就我用谷歌搜索,我只能看到它不是很困难,我所需要的只是在我的xml中添加一个版本标签,并在我的映射类中添加整数变量版本。 我的xml应该是这样的 当第二个用户保存时,hiber
存储这些数据后,当需要更新数据时,首先将JSON字符串解析为实体,然后更新属性,然后在Redis中刷新数据。所以Redis中的数据将是最新的数据。 当我们需要将Redis数据保存到MongoDB时,我们首先将JSON字符串解析为实体,然后使用Morphia DAO保存实体,但是我们遇到了这个异常: 我知道这一定是乐观锁的问题。我们如何解决这个并发异常?
在提交当前事务之前,当hibernate检查行的版本时,它应该发出一个sql语句来获取ithe行。 假设发出语句后,hibernate发现行版本没有更改,因此它应该继续提交事务。 否则,在行版本检查和提交之间会有一个很短的时间间隔,这可能会发生竞争条件。 请分享你的想法。
我正在浏览Spring Data MongoDB参考文档,发现示例有点过于简单。 特别是,我试图了解如何在并发环境中处理陈旧数据。例如,假设我有以下实体: 但是我有点担心,如果我想做的每种类型的更新都需要一个新的方法,那么我的存储库接口将无法控制地增长。 我意识到我实际上还没有提出一个问题,所以现在开始了:在MongoDB中使用Spring数据设计应用程序的最佳实践是什么?
我试图在不同的事务中更新同一行,以理解Hibernate的乐观锁定。 但是我没有得到任何StaleObjectStateException或任何其他异常。 我已经在我正在尝试执行的操作上方附加了代码。请让我知道..我错过了什么吗? 或者乐观锁定与我正在尝试做的事情不同。 在上面的代码中,我启动了两个线程“早些时候”和“晚些时候”,它们都从会话工厂获取会话对象,并从数据库加载相同的记录并同时更新它。