java - 如何使用复合 ID 解决 Session.get() 奇怪的行为?

标签 java hibernate composite-id

我正在尝试对声明复合 id 且没有映射复合标识符的对象执行 get session 。
使用的Hibernate版本是3.5.5。

获取代码是通用的,并读取包装实际数据的容器对象:

ClassMetadata metadata = 
          session.getSessionFactory().getClassMetadata(wrapper.getDomainClass());
Serializable id = metadata.getIdentifier(wrapper, EntityMode.POJO);
return session.get(wrapper.getDomainClass(), id, LockOptions.UPGRADE);

代码对实际映射一无所知,因此必须查阅有关 id 的元数据。

如果映射定义如下:

<hibernate-mapping default-access="field">
  <class name="Wrapper"
      entity-name="Data"
      table="DATA">
    <composite-id>
      <key-property name="identifier" column="identifier" />
      <key-property name="version" column="version" />
    </composite-id>

    <component name="domainObject" class="Data">
      <property name="source" column="source" />
    </component>                    
  </class>
</hibernate-mapping>

如果没有复合标识符类,id 等于对象本身,并且等于包装器引用。
当我执行 session.get() 而不是从数据库获取对象时,它返回与 id 中传递的相同对象(不是相等的对象,而是相同的对象实例)。
更新:事实上,session.get() 从数据库加载传递的 id 对象中的对象并将其返回。我最初认为它会跳过加载。

到目前为止我发现的解决方案是引入映射的复合标识符并将映射更改为:

<hibernate-mapping default-access="field">
  <class name="Wrapper"
      entity-name="Data1"
      table="DATA_1">
    <composite-id  class="SurrogateKey" mapped="true">
      <key-property name="identifier" column="identifier" />
      <key-property name="version" column="version" />
    </composite-id>

    <component name="domainObject" class="Data">
      <property name="source" column="source" />
    </component>                    
  </class>
</hibernate-mapping>

SurrogateKey 被定义为具有两个字段的对象,并根据需要使用 equals/hashcode。
通过此更改,metadata.getIdentifier() 返回的 id 是 SurrogateKey 的一个实例,session.get() 会从数据库中获取对象(如果存在)。

映射修复的问题是条件和 HQL 的属性名称从 identifier 更改为 id.identifier,这实际上破坏了许多现有代码。

我目前正在探索的事情是:

  1. 有没有办法让 session.get() 在不声明 Id 类的情况下工作(我知道这是一种不鼓励的做法,但所需的更改量可能会令人望而却步)?
  2. 替代方案是否可以告诉 hibernate 像以前一样处理属性,而不添加 id。在他们面前?
  3. 将 hibernate 升级到 v4(由于依赖项目和审批流程而不容易)?
  4. 还有其他可用的选项/解决方法吗?

到目前为止,我只设法使上述解决方案发挥作用,但我正在寻找侵入性较小的解决方案,并且希望能提供任何线索、建议、相关文档的指示。

最佳答案

第一个代码片段中的wrapper是什么?如果它是一个附加实体(我怀疑它是),显然,session.get()将返回具有相同标识符的附加实体,并且由于标识符是实体本身,因此它将返回给定的附加实体。 session 中任何给定实体始终只有一个实例。

现在,回答您的问题:

  1. 据我所知,它按预期工作。
  2. 没有。
  3. 这是一个问题吗?
  4. 最好的解决方法是做正确的事情并停止使用复合标识符。按照 Hibernate 的建议,使用单列、自动生成的 ID,一切都会变得更加简单。

关于java - 如何使用复合 ID 解决 Session.get() 奇怪的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11341621/

相关文章:

java - Couchbase - 使用大写单词通过正则表达式查找文档

hibernate - org.hibernate.MappingException : Could not determine type for: java. util.Set,在表 : USERS, 的列 : [org. hibernate.mapping.Column(invoices)]

c# - 是否可以通过 composite-id 的多对一键进行导航?

java - DocumentBuilder 解析 xml 错误

java - 将ArrayList插入MySQL

java - 路径中的 Ant 大写与小写字符

java - hibernate 一对多关系 - 子表不更新

java - 相同的查询方法结果不同;如果对象(未完全)加载到内存中,springboot和hibernate是否可以阻止查询?

java - 使用复合键的 Hibernate XML 子类化