2013-03-21 109 views
0

Conserider的一列几个表映射下表结构JPA - 休眠:在另一个

country 
======= 
id 
code 
name_id 

label 
====== 
id 
code 
label_value_id 

translations 
============= 
id 
ref_id 
language 
value 

现在我需要找到一个JPA映射到地图country:name_idlabel:label_value_id到翻译ref_id。我一直在用正确的英文术语来解释这种情况,但在体面的点击上空了。因此,数据库可以保存记录,如本例

country 
id: 1, code: BE, name_id: 30 

label 
id: 1, code: LABELA, label_value_id: 31 

translations 
id: 1, ref_id: 30, language: EN, value: BELGIUM 
id: 2, ref_id: 30, language: NL, value: BELGIE 
id: 3, ref_id: 31, language: EN, value: ALPHA_A 
id: 4, ref_id: 31, language: NL, value: ALFA_A 

在Java中我有3类

国家,标签和翻译,我会对国家@OneToMany关系和标签,这两个应该映射对翻译ref_id但我不知道如何编写我的@OneToMany代码来实现这一点。在正确的方向上的任何暗示将是非常理解的,溶液或手动

=====

更新2013-03-23

如上所述通过乔普,使用鉴别器是sollution BUT它没有开箱即用。我被迫使用hibernate注释@DiscriminatorOptions(force = true)。如果你不添加它,hibernate在获取所需的集合时完全忽略它的SQL查询中的Discriminator。

@Entity 
@Table(name = "testtranslations") 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name = "DTYPE", discriminatorType = DiscriminatorType.STRING) 
@DiscriminatorOptions(force=true) 
public class TestTranslation extends DomainObject { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -6211853644196769521L; 

    private long id; 
    private String language; 
    private String value; 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO, generator="testtranslations_seq_gen") 
    @SequenceGenerator(name="testtranslations_seq_gen", sequenceName="TESTTRANSLATIONS_SEQ") 
    @Column(name="testtranslation_id") 
    public long getId() { 
     return id; 
    } 

    @Column(name="language", length=3, nullable=false) 
    public String getLanguage() { 
     return language; 
    } 

    @Column(name="value") 
    public String getValue() { 
     return value; 
    } 

    @Override 
    public void setId(long id) { 
     this.id = id; 
    } 

    public void setLanguage(String language) { 
     this.language = language; 
    } 

    public void setValue(String value) { 
     this.value = value; 
    } 
} 


@Entity 
@Table(name = "testcountries") 
public class TestCountry extends DomainObject { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -9207081478447113501L; 

    private long id; 
    private String code; 
    private List<NameTranslation> name; 
    private List<DescriptionTranslation> description; 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO, generator="testcountries_seq_gen") 
    @SequenceGenerator(name="testcountries_seq_gen", sequenceName="TESTCOUNTRIES_SEQ") 
    @Column(name="country_id") 
    public long getId() { 
     return id; 
    } 

    @Column(name="iso_code", length=3, nullable=false) 
    public String getCode() { 
     return code; 
    } 

    @OneToMany(mappedBy="refId") 
    public List<NameTranslation> getName() { 
     return name; 
    } 

    @OneToMany(mappedBy="refId") 
    public List<DescriptionTranslation> getDescription() { 
     return description; 
    } 

    @Override 
    public void setId(long id) { 
     this.id = id; 
    } 

    public void setCode(String code) { 
     this.code = code; 
    } 

    public void setName(List<NameTranslation> name) { 
     this.name = name; 
    } 

    public void setDescription(List<DescriptionTranslation> description) { 
     this.description = description; 
    } 
} 

@Entity 
@DiscriminatorValue("NAMETRANSLATION") 
public class NameTranslation extends TestTranslation { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 7197732491071768673L; 

    private TestCountry refId; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "refId", nullable=false) 
    public TestCountry getRefId() { 
     return refId; 
    } 

    public void setRefId(TestCountry refId) { 
     this.refId = refId; 
    } 
} 

@Entity 
@DiscriminatorValue("DESCTRANSLATION") 
public class DescriptionTranslation extends TestTranslation { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = -4128287237786410515L; 

    private TestCountry refId; 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name = "refId", nullable=false) 
    public TestCountry getRefId() { 
     return refId; 
    } 

    public void setRefId(TestCountry refId) { 
     this.refId = refId; 
    } 
} 

我做了必要的Hibernate映射并写了DbUnit的测试负载是通过ID TestCountry用以下数据

<TESTCOUNTRIES COUNTRY_ID="1" VERSION="0" ISO_CODE="BE" /> 
<TESTTRANSLATIONS TESTTRANSLATION_ID="1" VERSION="0" LANGUAGE="EN" VALUE="Belgium" REFID="1" DTYPE="NAMETRANSLATION" /> 
<TESTTRANSLATIONS TESTTRANSLATION_ID="2" VERSION="0" LANGUAGE="NL" VALUE="Belgie" REFID="1" DTYPE="NAMETRANSLATION" /> 
<TESTTRANSLATIONS TESTTRANSLATION_ID="3" VERSION="0" LANGUAGE="EN" VALUE="BelgiumDesc" REFID="1" DTYPE="DESCTRANSLATION" /> 
<TESTTRANSLATIONS TESTTRANSLATION_ID="4" VERSION="0" LANGUAGE="NL" VALUE="BelgieDesc" REFID="1" DTYPE="DESCTRANSLATION" /> 

我希望这将帮助其他人在未来,我只是难过没有JPA溶剂,我不得不被迫使用hibernate注释。

+3

你是说你的refid列可以引用国家name_id或label_value_id?你如何区分两者? – Perception 2013-03-21 14:43:53

+1

如何为'country'和'label'和'translations'创建一个父类来引用这个父类? – BobTheBuilder 2013-03-21 14:45:51

+0

精确的原因可能是一件好事,因为它似乎是一个可变的设计。 – benzonico 2013-03-21 14:46:16

回答

1

有点困难,因为你有两个表1或表的外键2.

确实有在JPA存在鉴别理念,为表继承。然后从共同的抽象表中派生出两个表格,并且具有不同的鉴别器字段。一个example。尽管这有点不同。

P.S.使用搜索关键字discriminatorValue和discriminatorColumn查找更好的示例。

+0

如果我将使用继承来从翻译中继承Country和Label,那么Country和Label的所有记录都不会在同一个表中?我当然会有一个DTYPE专栏,告诉它是什么样的记录国家或标签,但所有的数据将在一个表中不是吗?我不认为我的DBA会喜欢这个想法:( – kenny 2013-03-21 15:51:27

+0

不,他们留在单独的表格 - 当你不这样做时@Inheritance(strategy = InheritanceType.SINGLE_TABLE)', – 2013-03-21 18:45:25

+0

Thnx Joop我会把它带到下一个技术会议,看看他们是否愿意 – kenny 2013-03-22 07:34:55