如何国际化Hibernate实体

use*_*038 11 java hibernate jpa internationalization

我正在尝试为java实体添加国际化(多语言)支持.在向每个新字段添加翻译时,我对所有选项都开放,尽可能少的样板代码.我不仅限于JPA,也可以使用hibernate注释.在最坏的情况下,普通sql也适合.可能有一些我没有找到的现成库.它不应该遵循我下面描述的想法.

理想情况下,我需要数据库看起来像这样:

i18n
+------+--------+------+
|  id  | locale | text |
+------+--------+------+
|  1   |   en   | foo  |
+------+--------+------+
|  1   |   de   | bar  |
+------+--------+------+
|  2   |   en   | foo2 |
+------+--------+------+
|  2   |   de   | bar2 |
+------+--------+------+

parent
+------+------+
|  id  | text |
+------+------+
|  99  |   1  |
+------+------+
|  100 |   2  |
+------+------+
Run Code Online (Sandbox Code Playgroud)

i18n是应该只包含3列的表:id,localetext.表parent有一列text(如果只有单个字段需要i18​​n,否则需要更多列),其中包含来自的值i18n.id.我在Parent类中尝试了以下映射:

@ElementCollection @CollectionTable(name="i18n", joinColumns = @JoinColumn(referencedColumnName="id"))
@MapKeyColumn(name="locale") @Column(name="text")
public Map<String, String> text = newHashMap();
Run Code Online (Sandbox Code Playgroud)

它似乎在禁用DDL生成时工作,我自己创建表,但是当启用DDL生成时,它会为它生成一个不必要的列i18n.parent_id和约束:

ALTER TABLE PUBLIC.I18N ADD CONSTRAINT 
PUBLIC.FK_HVGN9UJ4DJOFGLT8L78BYQ75I FOREIGN KEY(PARENT_ID) INDEX 
PUBLIC.FK_HVGN9UJ4DJOFGLT8L78BYQ75I_INDEX_2 REFERENCES 
PUBLIC.PARENT(ID) NOCHECK
Run Code Online (Sandbox Code Playgroud)

我怎样才能摆脱这个额外的列?是否可以避免从i18n表到parent表的引用?此链接使重用i18n表很困难.我要么需要在i18n表中保留一些鉴别器值,要么在整个数据库中使用GUID,因为不同表中的id会发生冲突.第一个选项意味着许多样板代码.第二个选项意味着在当前项​​目中要完成很多工作.

我需要一种可重用的方法来将i18n添加到实体中.我的父类看起来大致如此.并且将有几个这样的父类具有必须国际化的不同字段集.

@Entity
public class Parent {

    @Id @GeneratedValue
    public Long id;

    public String title; // must be in internationalized
    public String text; // must be in internationalized
    public String details; // must be in internationalized

    // ... other fields
}
Run Code Online (Sandbox Code Playgroud)

Ala*_*Hay 0

您不是只是@JoinColumn通过使用错误地 指定了

@JoinColumn(referencedColumnName="id"))
Run Code Online (Sandbox Code Playgroud)

而不是

@JoinColumn(name="id"))
Run Code Online (Sandbox Code Playgroud)

http://docs.oracle.com/javaee/6/api/javax/persistence/JoinColumn.html#referencedColumnName()

当在 CollectionTable 映射中使用时,引用的列位于包含集合的实体的表中

因此,本质上您是在父级中(重新)定义 ID 列,而 Hibernate 使用其默认命名策略在 i18n 中生成 FK 列。

使用这个:

@Entity
@Table(name = "parent")
public class Parent {

    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(name = "i18n", foreignKey = @ForeignKey(name = "ii8n_to_parent_fk"), joinColumns = @JoinColumn(name = "id"))
    @MapKeyColumn(name = "locale")
    @Column(name = "text")
    public Map<String, String> text = new HashMap<>();

}
Run Code Online (Sandbox Code Playgroud)

生成以下内容:

19:29:08.890 [main] DEBUG jdbc.sqlonly -  org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:51)
3. create table i18n (id bigint not null, text varchar(255), locale varchar(255) not null, primary 
key (id, locale)) 

19:29:09.464 [main] DEBUG jdbc.sqlonly -  org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:51)
3. alter table i18n add constraint ii8n_to_parent_fk foreign key (id) references parent 
Run Code Online (Sandbox Code Playgroud)