【发布时间】:2012-07-05 09:36:41
【问题描述】:
我正在尝试对声明复合 id 而没有映射复合标识符的对象执行获取会话。
使用的休眠版本是 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() 从数据库in 加载对象,传递的 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,这实际上破坏了许多现有代码。
我目前正在探索的事情是:
- 有没有办法让 session.get() 在不声明 Id 类的情况下工作(我知道这是一种不鼓励的做法,但所需的更改量可能会令人望而却步)?
- 是否可以告诉 hibernate 像以前一样处理属性,而不添加 id。在他们面前?
- 将 hibernate 升级到 v4(由于依赖项目和审批流程并不容易)?
- 还有其他可用的选项/解决方法吗?
到目前为止,我只设法使上述解决方案有效,但我正在寻找侵入性较小的解决方案,并希望能提供任何线索、建议和指向相关文档的指针。
【问题讨论】:
标签: java hibernate composite-id