2010-09-17 27 views
0

我有一个表类别和一个表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; 

与不正确的名称查询选择:

选择translatab0_.TranslatableDescriptionId为Translat4_13_1_,translatab0_.id为id1_,translatab0_.lang为Lang1_,translatab0_.id为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')

如果我将映射@JoinColumn更改为re

org.hibernate.MappingException:广告

@JoinColumn(name="TranslatableDescriptionId", referencedColumnName="id") 

我装我的应用程序时,遇到下列错误无法找到逻辑名称列:ID在org.hibernate.mapping.Table(类别)和其相关supertables和辅助表

良好的措施我也试过:

@JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId") 

这给我的错误:

org.hibernate.MappingException:无法找到逻辑名称列:TranslatableDescriptionId在org.hibernate.mapping.Table(类别)及其相关supertables和辅助表

到我应该做的有什么建议?我真想类别的translateableText遏制其描述所有的翻译,所以我真的想加入Category.TranslatableDescriptionId == TranslatableText.id

UPDATE1: TranslatableText是由许多实体使用,所以投入的categoryId在它和扭转关系不是一种选择。

UPDATE2: 我能够加载它说@JoinColumn(name="id"),但是这导致一个ClassCastException在休眠那里,而不是具有整数作为关键字,具有包含单个整数作为密钥数组。这不能被做成一个字符串,因此是适当的SQL。因此,它可能仍然不是映射我想

干杯

回答

2

这种映射是可能的,但不是很方便,因为你必须管理的手动TranslatableText身份(这就是为什么休眠抱怨非映射列TranslatableDescriptionId):

public class Category implements Serializable { 
    ... 
    private Long translatableDescriptionId; 

    @OneToMany 
    @JoinColumn(name="id", referencedColumnName="TranslatableDescriptionId") 
    private Set<TranslatableText> translatableText; 
    ... 
} 

所以,你需要手动分配唯一translatableDescriptionId s到的TranslatableText(类别中的所有“目标” ,项目,文件夹,如你所说)并手动设置这个值为idTranslatableText然后再坚持它(你不能只是将TranslatableText添加到Set)。

-

然而,更方便的设计是引入一个中间实体保持attatched到特定目标的所有transalations的身份:

public class Category { 
    ... 
    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "targetId") 
    private TranslationTarget target; 
} 

public class TranslationTarget { 
    @Id @GeneratedValue 
    private Long id; 

    @OneToMany 
    @JoinColumn(name = "targetId") 
    private Set<TranslatableText> texts; 
} 

-

create table Category (    
    targetId int, 
    ...);   

create table TranslationTargets (
    id int primary key 
);  

create table TranslatableText (    
    targetId int not null,    
    lang enum ('NO','EN','FR'),    
    text mediumtext,    
    primary key(targetId, lang)); 
+0

谢谢对于这个建议,我马上尝试一下这个设计并回报:-)然而,我有点困惑,因为我阅读它的方式只是把问题推到了我面前一步? – niklassaers 2010-09-17 11:34:46

+0

'name =“targetId”'分类指向Category.targetId,对不对?或者应该是'name =“id”',因为它指向TranslationTargets.id,就像TranslationTarget的'name =“targetId”'指向TranslatableText.targetId? – niklassaers 2010-09-17 11:45:07

+0

当这样做时,我得到以下例外。在我错过的映射中有什么吗? com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:'字段列表'中的未知列'texts0_.targetId' – niklassaers 2010-09-17 12:03:55