我正在使用具有扩展会话/自动版本控制的标准乐观并发控制方案。我有一个实体,我在第一个事务中加载,呈现给用户进行修改并保存在第二个事务中,两个事务共享同一个会话。session.flush()
在第二个事务结束时以某种方式修改实体之后StaleObjectStateException
,如果检测到版本不一致,则可能会抛出一个错误,这意味着并发事务已在其间保存了实体的下一个版本。
我想以最简单的方式处理这样的错误——只是重新加载丢失当前更改的实体并继续编辑和保存。首先我尝试了这个:
session.refresh(entity);
但是在我修改并尝试保存这个刷新的实体之后,我仍然得到相同的StaleObjectStateException
结果,即使它确实被刷新并且版本号看起来是一致的;是的,我知道不鼓励refresh()
在扩展会话中使用,但不明白为什么。这种行为是否与不鼓励它的原因有关?
接下来我尝试了以下方法来避免使用session.refresh()
:
session.evict(entity);
entity = session.load(MyEntity.class, id);
但它仍然会导致在StaleObjectStateException
拯救确实不是陈旧的实体时被提升。
我设法应对异常的唯一方法是:
session.clear();
entity = session.load(MyEntity.class, id);
但与我的具体实体不session.clear()
一样吗?session.evict()
要恢复,我的问题是:
- 除非完成,否则为什么
StaleObjectStateException
仍然会在重新加载的实体上抛出session.clear()
? - 重新加载已在同一会话中加载的实体的正确方法是什么,为什么
refresh()
不好?这种实现对话的方法有问题吗?
我使用的是 Hibernate 4.1.7.Final,没有二级缓存。
如果我的问题重复,我很抱歉,但我找不到深刻的解释......