我正在开发一个连接到Oracle 10g数据库的Hibernate 3.5.6.FINAL的应用程序,我需要防止特定实体的脏读。
为此,我正在使用JPA的标准版本列。它在我们的Hibernate XML映射上配置如下:
<version name="lockVersion" column="LOCK_VERSION"/>
但显然我们现在需要在所有相关实体上使用Version。
特别是,我们与另一个实体EntityB
建立了多对一关系,我们不需要在这些关系中使用版本,因为我们不对这些表进行插入或更新。这种关系映射如下:
<many-to-one name="entityB" column="ENTITY_B" class="com.example.EntityB" lazy="false" update="false" insert="false" cascade="none" />
问题在于,每当我们尝试对原始实体进行更新时,我们都会出现以下错误:
InvalidDataAccessApiUsage:object引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:
显然,Hibernate认为EntityB
的实例是暂时的,因为它没有Version
(因此,Version = null
);但它不包含Version
字段,因为它是无版本的,不是因为它是瞬态的。实际上,该实例是从数据库中获取的,它有一个主键。
有没有办法配置Hibernate,所以不检查相关对象的版本?
作为一个注释:我试图用Hibernate非版本机制实现Optimistic Lock,但我们的应用程序使用Detached Mode;所以这种方法对我们来说是不可行的。
答案 0 :(得分:0)
在我看来,你的实体B获得了#34;分离&#34;。
如果它是一个webapp,或多或少的标准方法将是以下。
让entityA成为具有(非版本化)entityB作为字段的实体(为简洁起见,我不区分类和对象)。
您的网页在加载页面时将数据与entityA的版本一起发送给更新实体A.输入事务后,立即从数据库加载entityA,并将其当前版本与从网页到达的版本进行比较。如果当前版本较大(这意味着更新),则抛出乐观锁定异常。如果没有,则使用从网页到达的数据更新从数据库加载的entityA的字段(不会自动完成后增加版本),这就是:退出事务后,新值将提交entityA的字段 - 除非某些其他事务成功在您之前更新数据库中的entityA,在这种情况下,它是Hibernate,它会抛出一个乐观的锁定相关异常。
因此,如果从您的交易中抛出此类异常,其含义为&#34;某些其他交易已经修改了数据&#34;,并且需要显示相关消息(通常在webapps中此消息显示&#34;数据被另一个用户修改了#34;)。