Java 在Hibernate中映射复杂值对象
我已经在网上问过这个问题了,但我想我也应该在这里问 我试图映射以下模型,同时保留Java 在Hibernate中映射复杂值对象,java,hibernate,domain-driven-design,hibernate-xml-mapping,Java,Hibernate,Domain Driven Design,Hibernate Xml Mapping,我已经在网上问过这个问题了,但我想我也应该在这里问 我试图映射以下模型,同时保留TranslatedText和Translation值对象的值语义: 这两个值都作为从属对象 理想情况下,我会将翻译文本映射为问题中的,将翻译映射为翻译文本中的 如果问题只引用了一个翻译文本,那么映射就很简单了,但是由于它引用了两个,我需要一种基于持有值的属性名称的鉴别器(title或description)要使用由(问题\u id、属性\u名称、语言\u代码)组成的外键映射翻译 一个问题是,propertyNam
TranslatedText
和Translation
值对象的值语义:
这两个值都作为从属对象
理想情况下,我会将翻译文本
映射为问题
中的
,将翻译
映射为翻译文本
中的
如果问题
只引用了一个翻译文本
,那么映射就很简单了,但是由于它引用了两个,我需要一种基于持有值的属性名称的鉴别器(title
或description
)要使用由(问题\u id、属性\u名称、语言\u代码)
组成的外键映射翻译
一个问题是,propertyName
不是模型的一部分,也不应该是模型的一部分,但是我还没有找到一种方法来强制Hibernate插入一个不来自模型的值
因此,我试图改变模型,引入专门的Title
和Description
类,这样我就有了一个类型
,可以用作鉴别器
最后,这并没有起到多大作用:
<component name="title" class="TranslatedText">
<bag name="translations" table="Translation">
<key>
<!-- PROBLEM: Could not find a way to create a custom join expression on question.id and question.title.type in here. -->
</key>
<composite-element class="Translation">
<!-- PROBLEM: Could not found a way to make Hibernate insert title.type from here, without having this value on the Translation object. -->
<property name="languageCode" type="string" column="language_code"/>
<property name="text" type="string"/>
</composite-element>
</bag>
</component>
带有
通过使用
将TranslatedText
映射为问题
中的一个实体,然后将TranslatedText
映射为TranslatedText
中的一组值,我成功地获得了接近我需要的东西,但这种方法的主要问题是,没有简单的方法可以摆脱孤立的TranslatedText
和Translation
。我要么用DB触发器,要么用预定的进程
结论
在这一点上,我的印象是Hibernate不够灵活,无法用正确的语义映射初始模型,但希望我错了,有办法做到这一点。我还没有找到将它们映射为值的方法。不过,下一个解决方案是可行的,它可能会对您有所帮助。我删除了
TranslatedText
,并将问题
直接链接到翻译集
@Entity
public class Question {
@Id
private String id;
@JoinTable
@OrderColumn
@OneToMany(fetch = EAGER, cascade = ALL)
private List<Translation> titleTranslations;
@JoinTable
@OrderColumn
@OneToMany(fetch = EAGER, cascade = ALL)
private List<Translation> descriptionTranslations;
}
嗯,
TranslatedText
很有用,因为它确保了每个代码只有一个翻译,所以我不能直接删除它,除非我用DB约束强制执行规则,但模型的表现力就没有那么强了。如果是java,我可以使用Set
,但我们不能这样做,因为模型实际上是用ColdFusion(是的,那是一种可怕的语言)编写的,而不是java。没有上下文,很难理解您的约束,但通过将所有三个类都设置为@Entity
(每个都有自己的@Id
)。这样可以吗?如果可以的话,我可以准备这样的配置。好吧,就像我说的,我已经通过将TranslatedText
映射为一个实体来实现了。但是,在这种情况下,我不能做cascade delete orphan
,因为我使用了多对一
。值对象只是简单的不可变值,如Date
或Integer
。将它们映射为hibernate组件可以解决孤立的问题。事实上,我很惊讶如此常见的场景如此难以映射。
@Entity
public class Translation {
@Id
private String id;
private String languageCode;
private String text;
}