OK、私はそれを持っていると思います。私の質問の最初のリンクの単純化されたバージョンが動作し、Localizedエンティティ(メインエンティティの各テキスト要素ごとに異なるjoinColumnを持つ)にManyToOne関係を使用するだけで、そのローカライズされたエンティティ内のMapの単純なElementCollection 。私は、各ロケール(名前と説明)ごとに複数のエントリが必要な2つのテキスト要素を持つ、ただ1つのエンティティ(カテゴリ)で、私の質問とは若干異なる例をコーディングしました。
これは、MySQLに行くEclipselink 2.4に対して行われたことに注意してください。
最初のリンクからわかるように、ElementCollectionを使用すると、別のテーブルが作成され、変換可能な文字列の2つのテーブルが作成されます.1つはID(Locaised)すべての地図情報を保持するメインのFK(Localised_strings)。 Localised_stringsという名前は自動/デフォルトの名前です。@CollectionTableアノテーションで別の名前を使用できます。全体として、これはDBの観点からは理想的ではありませんが、世界の終わりではありません。
2番目は、少なくともEclipselinkとMySQLの組み合わせで、単一の(自動生成された)列テーブルに永続化するとエラーが発生します:(したがって、エンティティのダミー列の既定値を追加しました。純粋にその問題を克服することである
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)
Aメイン...
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
と、次の表のエントリを: - em.removeのコメントを外す
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"
は正しくカテゴリーの両方を削除し、それがLocaised/Localised_stringsエントリを関連付けられています。
誰もが将来誰かを助けることを願っています。
これは素晴らしいです! JPA2.0 + Hibernate 4.2 + MSSQL2008でうまく動作します。パフォーマンスなどの可能性のある問題について考えましたか?私は熱心にロードされたローカライズされた文字列を取得したいと思います。ところで、ローカライズされたテーブルのダミー列は必要ありません。 – curious1
上記のように、ダミー列の問題はEclipselinkとMySQLの特定の組み合わせにまで及んでいると思います.HibernateとMSQLのコンボのように見えますが、単一の自動列が保持されます。 私が探していた特定のアプリケーションのボリューム要件は小さかったので、パフォーマンス上の問題に多大な時間を費やすことはありませんでした。 – IrishDubGuy
spring data restアプリケーションのaccept-languageヘッダーの値に対応する文字列のみを取得するのが最善の方法ですか? – aycanadal