乐观锁定具有非版本化多对一关系的版本化实体



我正在使用Hibernate 3.5.6.FINAL开发一个连接到Oracle 10g数据库的应用程序,我需要防止对特定实体进行脏读取。

为此,我使用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:对象引用未保存的瞬态实例-在刷新前保存瞬态实例:

显然,Hibernate认为EntityB的实例是瞬态的,因为它没有Version(因此是Version = null);但它不包括Version字段,因为它是未转换的,而不是因为它是瞬态的。实际上,该实例是从数据库中提取的,它有一个主键。

有没有什么方法可以配置Hibernate,使其不检查相关对象的版本?

注意:我曾尝试用Hibernate非版本机制实现OptimisticLock,但我们的应用程序使用分离模式;所以这种方法对我们来说是不可行的。

在我看来,您的实体B已"分离"。

如果它是一个网络应用程序,或多或少的标准方法如下。

让entityA是将(非版本的)entityB作为字段的实体(为了简洁起见,我不区分类和对象)。

您的网页在加载页面时发送数据以更新entityA以及entityA的版本。一旦输入了事务,就从数据库中加载entityA,并将其当前版本与网页中的版本进行比较。如果当前版本较大(意味着更新),则抛出乐观锁定异常。如果没有,则使用从网页到达的数据更新从数据库加载的entityA的字段(由于它是自动完成的,因此不增加版本),就这样:一旦您退出事务,entityA字段的新值就会被提交-除非在您之前有其他事务成功更新了数据库中的entityA,在这种情况下,是Hibernate抛出了一个乐观锁定相关的异常。

因此,如果您的交易中抛出了此类异常,则意味着"其他交易已经修改了数据",并且需要显示相关消息(通常在网络应用程序中,该消息会显示"数据被其他用户修改")。

最新更新