2013-03-21 108 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