繁体   English   中英

多语言JPA实体映射

[英]Multilingual JPA entity mapping

使用此示例:

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());

正如我在评论中所说,我认为最好的解决方案是对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)访问名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM