2015-04-18 21 views
1

這個例子:多語種JPA實體映射

CREATE TABLE IF NOT EXISTS COUNTRY (
    COUNTRY_CODE   VARCHAR(3) NOT NULL, 
    DIALLING_CODE   VARCHAR(5) NOT NULL, 
    CREATION_TIMESTAMP  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    CREATED_BY    VARCHAR(20) NOT NULL, 
    LAST_UPDATE_TIMESTAMP TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP, 
    LAST_UPDATED_BY   VARCHAR(20), 
    DELETION_TIMESTAMP  TIMESTAMP NULL, 
    DELETED_BY    VARCHAR(20), 

    PRIMARY KEY(NUMERIC_CODE), 
    UNIQUE(ALPHA2_CODE), 
    UNIQUE(ALPHA3_CODE), 
    UNIQUE(DIALLING_CODE), 
    FOREIGN KEY(CREATED_BY) REFERENCES USER(USER_NAME), 
    FOREIGN KEY(LAST_UPDATED_BY) REFERENCES USER(USER_NAME), 
    FOREIGN KEY (DELETED_BY) REFERENCES USER(USER_NAME) 
) CHARACTER SET utf8; 

CREATE TABLE IF NOT EXISTS COUNTRY_NAME (
    COUNTRY_CODE   VARCHAR(3) NOT NULL, 
    LANGUAGE_CODE   VARCHAR(2) NOT NULL, 
    NAME     VARCHAR(20) NOT NULL, 
    CREATION_TIMESTAMP  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    CREATED_BY    VARCHAR(20) NOT NULL, 
    LAST_UPDATE_TIMESTAMP TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP, 
    LAST_UPDATED_BY   VARCHAR(20), 

    PRIMARY KEY (COUNTRY_CODE, LANGUAGE_CODE), 
    FOREIGN KEY (COUNTRY_CODE) REFERENCES COUNTRY (COUNTRY_CODE), 
    FOREIGN KEY (LANGUAGE_CODE) REFERENCES LANGUAGE (ALPHA2_CODE), 
    FOREIGN KEY (CREATED_BY) REFERENCES USER(USER_NAME), 
    FOREIGN KEY (LAST_UPDATED_BY) REFERENCES USER(USER_NAME) 
) CHARACTER SET utf8; 

爲國家的JPA表示如下:

@XmlRootElement 
@Entity 
@Table(name="COUNTRY") 
@Access(AccessType.FIELD) 
@Cacheable 
public class Country extends AbstractSoftDeleteAuditableEntity<String> implements za.co.sindi.persistence.entity.Entity<String>, Serializable { 

    private static final long serialVersionUID = -4019436514961967327L; 

    @Id 
    @Column(name="COUNTRY_CODE", length=3, nullable=false) 
    @Size(min=3, max=3) 
    @Pattern(regexp="^\\d{3}$") 
    private String id; 

    @Column(name="DIALLING_CODE", length=5, nullable=false) 
    @Pattern(regexp="^\\+[0-9]{2,5}$") 
    private String diallingCode; 

    @OneToMany(cascade= CascadeType.ALL, mappedBy="country") 
    private List<CountryName> names; 


    /* (non-Javadoc) 
    * @see za.co.sindi.entity.IDBasedEntity#getId() 
    */ 
    public String getId() { 
     // TODO Auto-generated method stub 
     return id; 
    } 

    /* (non-Javadoc) 
    * @see za.co.sindi.entity.IDBasedEntity#setId(java.io.Serializable) 
    */ 
    public void setId(String id) { 
     // TODO Auto-generated method stub 
     this.id = id; 
    } 

    /** 
    * @return the diallingCode 
    */ 
    public String getDiallingCode() { 
     return diallingCode; 
    } 

    /** 
    * @param diallingCode the diallingCode to set 
    */ 
    public void setDiallingCode(String diallingCode) { 
     this.diallingCode = diallingCode; 
    } 

    /** 
    * @return the names 
    */ 
    public List<CountryName> getNames() { 
     return names; 
    } 

    /** 
    * @param names the names to set 
    */ 
    public void setNames(List<CountryName> names) { 
     this.names = names; 
    } 
} 

利用上述模型,我將不得不重複names屬性找到一個CountryName它與語言代碼相匹配。

有沒有更好的方法檢索基於語言代碼的CountryCountryName?如果沒有,我怎麼能實現更簡單的方法,可以讓我拉用語言代碼Country信息的實體像如下:

public class Country implements Serializable { 
     private static final long serialVersionUID = -4019436514961967327L; 

     @Id 
     @Column(name="COUNTRY_CODE", length=3, nullable=false) 
     @Size(min=3, max=3) 
     @Pattern(regexp="^\\d{3}$") 
     private String id; 

     @Column(name="DIALLING_CODE", length=5, nullable=false) 
     @Pattern(regexp="^\\+[0-9]{2,5}$") 
     private String diallingCode; 

     private String name; 

     private Language language; 


     //Getters and setters will be auto generated here.... 
} 

這樣一來,可以做到這一點:

Country country = countryDAO.find(countryCode); 
System.out.println(country.getName()); 
+0

爲什麼不使用一個單獨的查詢只是爲了'CountryName'? –

+0

我想過了,那就意味着我必須創建一個'CountryNameDAO',然後因爲我始終使用DAO模式。 –

+0

如果這不是你想要做的(雖然它可能是一個最好的選擇),你可能會添加一個'@Transient java.util.Map'字段到'Country'實體,你可以用'CountryName'填充。然後你可以通過'country.getName(countryCode)'來訪問它。但是,除非您緩存國家/地區數據,否則性能增益可能不會很高。 –

回答

0

正如我在評論中所說的,我認爲最好的解決方案是爲CountryName使用一個單獨的查詢(和DAO),因爲當你只需要指定countryCode時,它將避免加載不必要的國家名稱。

一種選擇是使用@Transient java.util.Map字段,將載有國名,以countryCode作爲地圖的關鍵,

@Transient 
private Map<String, CountryName> countryNameMap; 
... 
public CountryName getName(String countryCode) { 
    if (countryNameMap == null) { 
     countryNameMap = loadNamesIntoMap(); // a loop with countryNameMap.put(countryName.getCountryCode(), countryName) 
    } 
    return countryNameMap.get(countryCode); 
} 

另一個有趣的選項是實際使用java.util.Map的關係CountryCountryName

之間
@OneToMany(mappedBy="country") 
@MapKey(name="countryCode") 
private Map<String, CountryName> names; 

然後,您將使用country.getNames().get(countryCode)訪問該名稱。

+0

我使用了單獨的DAO,因爲需要在'CountryName'上添加不同的查詢,因此您的第一條語句就是實際的解決方案。謝謝。 –