Hibernate:与多键表的键之一连接
我有一个表 Category 和一个表 TranslatableText。类别是这样的
create table Category (
id int not null,
parent_id int default 0,
TranslatableDescriptionId int default 1,
primary key(id));
create table TranslatableText (
id int not null,
lang enum ('NO','EN','FR'),
text mediumtext,
primary key(id, lang));
在我的类别实体中,我定义了一个映射:
@Fetch(FetchMode.SUBSELECT)
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@OneToMany(fetch=FetchType.LAZY)
@JoinColumn(name="TranslatableDescriptionId")
@ForeignKey(name="FK_TranslatableTextId")
private Set<TranslatableText> translatableText;
但是当它执行时,它尝试访问 TranslatableDescriptionId,而不是 id。即使 TranslatableText 实体已定义
@Id
@Column(name = "id", nullable = false)
private Integer id;
@Id
@Column(name = "lang", nullable = false)
@Enumerated(EnumType.STRING)
private String lang;
@Column(name = "text", length = 400, nullable = false)
private String text;
选择了不正确名称的查询:
select translatab0_.TranslatableDescriptionId as Translat4_13_1_、translatab0_.id as id1_、translatab0_.lang as Lang1_、translatab0_.id as id22_0_、translatab0_.lang as Lang22_0_、translatab0_.text as来自 tblTranslateableText translatab0_ 的 Text22_0_ 其中 translatab0_.TranslatableDescriptionId in ('126', '119', '103', '116', '121', '107', '113', '101', '109', '105', '123', '106', '125', '124', '114')
如果我将映射 @JoinColumn 更改为读取,则
@JoinColumn(name="TranslatableDescriptionId", referencedColumnName="id")
在加载我的应用程序时会收到以下错误:
org.hibernate.MappingException: 无法找到带有以下内容的列逻辑名称: org.hibernate.mapping.Table(Category) 中的 id 及其相关的超级表和辅助表
为了更好的措施,我也尝试过:
@JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId")
这给了我错误:
org.hibernate.MappingException:无法找到具有逻辑名称的列:TranslatableDescriptionId在 org.hibernate.mapping.Table(Category) 及其相关的超级表和辅助表中
对我应该做什么有什么建议吗?我真的希望类别的translatableText包含其描述的所有翻译,所以我真的想加入Category.TranslatableDescriptionId==TranslatableText.id
UPDATE1: TranslatableText 被许多实体使用,因此在其中放入 CategoryId 并反转关系不是一种选择。
更新2: 我能够加载它说 @JoinColumn(name="id")
,但这导致了 Hibernate 中的 ClassCastException,其中它没有一个 Integer 作为键,而是一个包含单个值的数组整数作为键。无法将其转换为字符串,因此无法转换为正确的 SQL。所以这可能仍然不是我想要的映射
Cheers
Nik
I've got a table Category and a table TranslatableText. The category is like this
create table Category (
id int not null,
parent_id int default 0,
TranslatableDescriptionId int default 1,
primary key(id));
create table TranslatableText (
id int not null,
lang enum ('NO','EN','FR'),
text mediumtext,
primary key(id, lang));
In my Category entity I've defined a mapping:
@Fetch(FetchMode.SUBSELECT)
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@OneToMany(fetch=FetchType.LAZY)
@JoinColumn(name="TranslatableDescriptionId")
@ForeignKey(name="FK_TranslatableTextId")
private Set<TranslatableText> translatableText;
But when it executes, it tries to access TranslatableDescriptionId, not id. Even if the TranslatableText entity has defined
@Id
@Column(name = "id", nullable = false)
private Integer id;
@Id
@Column(name = "lang", nullable = false)
@Enumerated(EnumType.STRING)
private String lang;
@Column(name = "text", length = 400, nullable = false)
private String text;
The query with the incorrect name selected:
select translatab0_.TranslatableDescriptionId as Translat4_13_1_, translatab0_.id as id1_, translatab0_.lang as Lang1_, translatab0_.id as id22_0_, translatab0_.lang as Lang22_0_, translatab0_.text as Text22_0_ from tblTranslateableText translatab0_ where translatab0_.TranslatableDescriptionId in ('126', '119', '103', '116', '121', '107', '113', '101', '109', '105', '123', '106', '125', '124', '114')
If I change the mappings @JoinColumn to read
@JoinColumn(name="TranslatableDescriptionId", referencedColumnName="id")
I get the following error when loading my app:
org.hibernate.MappingException: Unable to find column with logical name: id in org.hibernate.mapping.Table(Category) and its related supertables and secondary tables
For good measure I also tried:
@JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId")
That gave me the error:
org.hibernate.MappingException: Unable to find column with logical name: TranslatableDescriptionId in org.hibernate.mapping.Table(Category) and its related supertables and secondary tables
Any suggestions to what I should do? I really want Category's translateableText to contain all the translations for its description, so I really want to join Category.TranslatableDescriptionId==TranslatableText.id
UPDATE1:
TranslatableText is used by many entities, so putting in a categoryId in it and reversing the relationship is not an option.
UPDATE2:
I was able to load it saying @JoinColumn(name="id")
, but this led to a ClassCastException in Hibernate where it, instead of having an Integer as a key, has an Array containing a single Integer as a key. This fails to be made into a String and thus proper SQL. So it's probably still not the mapping I want
Cheers
Nik
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这种映射是可能的,但不是很方便,因为您必须手动管理
TranslatableText
的标识(这就是 Hibernate 抱怨非映射列TranslatableDescriptionId
的原因):因此,您需要手动将唯一的
translatableDescriptionId
分配给TranslatableText
的所有“目标”(如您所说的类别、项目、文件夹),并手动将此值设置为在持久化之前,先检查
(您不能只将TranslatableText
的 idTranslatableText
添加到Set
中)。--
然而,更方便的设计是引入一个中间实体来保持所有附加到特定目标的翻译的身份:
-
This kind of mapping is possible, but not very convenient because you'll have to manage identity of
TranslatableText
s manually (that's why Hibernate complains about non-mapped columnTranslatableDescriptionId
):So, you need to manually assign unique
translatableDescriptionId
s to all "targets" ofTranslatableText
(categories, items, folders as you say) and manually set this values asid
ofTranslatableText
before persisting it (you can't just addTranslatableText
into theSet
).--
However, the more convenient design is to introduce an intermediate entity to keep the identity of all transalations attatched to a specific target:
-