【问题标题】:Optimistic Lock versioned entity with non-versioned many-to-one relationship具有非版本化多对一关系的乐观锁版本化实体
【发布时间】:2017-10-23 20:49:42
【问题描述】:

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

为此,我使用了 JPA 的标准版本列。它在我们的 Hibernate XML 映射中配置如下:

<version name="lockVersion" column="LOCK_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 非版本机制实现 Optimistic Lock,但我们的应用程序使用分离模式;所以这种方法对我们来说是不可行的。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    在我看来,您的 entityB 已“分离”。

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

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

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

    因此,如果从您的事务中抛出此类异常,则表示“其他一些事务已经修改了数据”,并且需要显示相关消息(通常在 webapps 中,此消息说“数据已被另一个用户修改” )。

    【讨论】:

    • 哦,也许我原来的帖子不清楚,但我的问题是父实体是从数据库加载并更新的,但是 Hibernate 抛出一个异常,说明 EntityB 是瞬态的,这不是. EntityB 未被修改,不应更新。
    • "..是父实体从数据库加载并更新,但 Hibernate 抛出异常,说明 EntityB 是瞬态的.." - 都在同一个事务中?如果是,您是否正在以某种方式修改包含对 entityB 的引用的字段?
    • 不是同一个事务,因为我们使用的是分离模式;但都在相同的请求中。我们从请求处理程序接收一个 ID,加载原始实体的实例,使用 EntityB 属性检查一些依赖字段而不更改任何值,对原始实例执行一些更改,然后更新数据库上的原始实体。这就是错误出现的时候,说明 EntityB 的实例是瞬态的。我读过,当Version 处于活动状态时,EntityManager 使用它的值来检查所有对象是否都在持久上下文中;我需要为 EntityB 避免这种情况
    • 重要的是事务,而不是请求。如果您退出交易,您的实体将变得“分离”,它所指的 entityB 也是如此。然后,当您尝试“保存或更新”您的分离实体 A 时,它会给出错误,因为它引用了您不“保存或更新”的分离实体 B。您的选择之一可能是在保存 entityA 之前加载 entityB 并设置 entityA 的相应字段。由于entityB不被修改,所以可以缓存(Hibernate二级缓存),因此加载entityB不会影响性能。
    猜你喜欢
    • 2011-08-18
    • 2020-11-26
    • 2012-12-17
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2012-03-05
    • 2023-01-12
    相关资源
    最近更新 更多