【问题标题】:Best practice to avoid 'A different object with the same identifier value was already associated with the session'避免“具有相同标识符值的不同对象已与会话关联”的最佳实践
【发布时间】:2020-10-16 06:32:16
【问题描述】:

我认为这是一个常见的程序

  • 通过休眠加载实体
  • 将其存储在会话变量中
  • 更改属性
  • 稍后保存

在任何情况下当前会话已经加载对象时,避免错误A different object with the same identifier value was already associated with the session 的常见做法是什么?

  • 使用合并?
  • 避免之前加载相同的对象?
  • 刷新休眠会话并分离另一个实例?
  • 从会话中检索对象并手动复制会话中实例的更改?
  • 使用 DTO 并且只将 id 存储在会话处理程序中?
  • 还有其他想法吗?

【问题讨论】:

标签: hibernate jpa


【解决方案1】:

我猜最佳实践是非常固执己见的。最后,您必须选择最适合您的用例的方法。我个人使用了以下方法:

  • 使用EntityManager.merge - 它工作起来很简单,但是您必须在要合并或单独合并的关联上正确配置CascadeType.MERGE。不过,这可能并不适合所有用例,并会导致大量更新
  • 从会话中获取当前对象并应用更改 - 如果我想完全控制可以更改的内容并可能在我看到某些属性值更改时触发其他更改,我通常会这样做,但这是相当繁琐的代码写
  • 使用 DTO - 这类似于“从会话中获取当前对象并应用更改”,因为您必须以某种方式将 DTO 映射到实体

话虽如此,我更喜欢使用 DTO 方法,但使用支持脏跟踪的 Blaze-Persistence Entity Views 仅更新真正更改的内容。

我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

查看文档以了解更多信息:https://persistence.blazebit.com/documentation/1.5/entity-view/manual/en_US/#updatable-mappings-basic

默认刷新策略使用 DML 查询,因此除了持久化对象之外没有与持久化上下文/会话的交互,但是如果需要,还有一个实体刷新策略可以通过更改持久化上下文中的对象来工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 2013-08-30
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多