好的,我想我有它。看起来我的问题中第一个链接的简化版本将起作用,只需使用与本地化实体的多对一关系(主实体中的每个文本元素都有不同的 joinColumn)和该本地化实体中的 Map 的简单 ElementCollection . 我编写了一个与我的问题略有不同的示例,只有一个实体(类别),有两个文本元素,每个语言环境需要多个条目(名称和描述)。
请注意,这是针对 Eclipselink 2.4 转到 MySQL 的。
关于这种方法的两个注意事项 - 正如您在第一个链接中看到的那样,使用 ElementCollection 会强制创建一个单独的表,这会导致可翻译字符串的两个表 - 一个只保存 ID(本地化),它是主要的 FK一个(Localised_strings)包含所有地图信息。名称 Localised_strings 是自动/默认名称 - 您可以将另一个名称与 @CollectionTable 注释一起使用。总的来说,从数据库的角度来看,这并不理想,但也不是世界末日。
其次是,至少对于我的 Eclipselink 和 MySQL 的组合,坚持到单个(自动生成的)列表会产生错误:(所以我在实体中添加了一个虚拟列 wa 默认值,这纯粹是为了克服那个问题。
import java.io.Serializable;
import java.lang.Long;
import java.lang.String;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.*;
@Entity
public class Category implements Serializable {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="NAME_ID")
private Localised nameStrings = new Localised();
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="DESCRIPTION_ID")
private Localised descriptionStrings = new Localised();
private static final long serialVersionUID = 1L;
public Category() {
super();
}
public Category(String locale, String name, String description){
this.nameStrings.addString(locale, name);
this.descriptionStrings.addString(locale, description);
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName(String locale) {
return this.nameStrings.getString(locale);
}
public void setName(String locale, String name) {
this.nameStrings.addString(locale, name);
}
public String getDescription(String locale) {
return this.descriptionStrings.getString(locale);
}
public void setDescription(String locale, String description) {
this.descriptionStrings.addString(locale, description);
}
}
import java.util.HashMap;
import java.util.Map;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Localised {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private int dummy = 0;
@ElementCollection
private Map<String,String> strings = new HashMap<String, String>();
//private String locale;
//private String text;
public Localised() {}
public Localised(Map<String, String> map) {
this.strings = map;
}
public void addString(String locale, String text) {
strings.put(locale, text);
}
public String getString(String locale) {
String returnValue = strings.get(locale);
return (returnValue != null ? returnValue : null);
}
}
所以这些生成表如下: -
CREATE TABLE LOCALISED (ID INTEGER AUTO_INCREMENT NOT NULL, DUMMY INTEGER, PRIMARY KEY (ID))
CREATE TABLE CATEGORY (ID BIGINT AUTO_INCREMENT NOT NULL, DESCRIPTION_ID INTEGER, NAME_ID INTEGER, PRIMARY KEY (ID))
CREATE TABLE Localised_STRINGS (Localised_ID INTEGER, STRINGS VARCHAR(255), STRINGS_KEY VARCHAR(255))
ALTER TABLE CATEGORY ADD CONSTRAINT FK_CATEGORY_DESCRIPTION_ID FOREIGN KEY (DESCRIPTION_ID) REFERENCES LOCALISED (ID)
ALTER TABLE CATEGORY ADD CONSTRAINT FK_CATEGORY_NAME_ID FOREIGN KEY (NAME_ID) REFERENCES LOCALISED (ID)
ALTER TABLE Localised_STRINGS ADD CONSTRAINT FK_Localised_STRINGS_Localised_ID FOREIGN KEY (Localised_ID) REFERENCES LOCALISED (ID)
一个主要测试它...
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
public class Main {
static EntityManagerFactory emf = Persistence.createEntityManagerFactory("javaNetPU");
static EntityManager em = emf.createEntityManager();
public static void main(String[] a) throws Exception {
em.getTransaction().begin();
Category category = new Category();
em.persist(category);
category.setName("EN", "Business");
category.setDescription("EN", "This is the business category");
category.setName("FR", "La Business");
category.setDescription("FR", "Ici es la Business");
em.flush();
System.out.println(category.getDescription("EN"));
System.out.println(category.getName("FR"));
Category c2 = new Category();
em.persist(c2);
c2.setDescription("EN", "Second Description");
c2.setName("EN", "Second Name");
c2.setDescription("DE", "Zwei Description");
c2.setName("DE", "Zwei Name");
em.flush();
//em.remove(category);
em.getTransaction().commit();
em.close();
emf.close();
}
}
这会产生输出:-
This is the business category
La Business
和下表条目:-
Category
"ID" "DESCRIPTION_ID" "NAME_ID"
"1" "1" "2"
"2" "3" "4"
Localised
"ID" "DUMMY"
"1" "0"
"2" "0"
"3" "0"
"4" "0"
Localised_strings
"Localised_ID" "STRINGS" "STRINGS_KEY"
"1" "Ici es la Business" "FR"
"1" "This is the business category" "EN"
"2" "La Business" "FR"
"2" "Business" "EN"
"3" "Second Description" "EN"
"3" "Zwei Description" "DE"
"4" "Second Name" "EN"
"4" "Zwei Name" "DE"
取消注释 em.remove 会正确删除 Category 及其关联的 Localised/Localised_strings 条目。
希望对未来的人有所帮助。