【发布时间】:2017-02-03 21:48:46
【问题描述】:
我正在尝试向 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 |
+------+------+
i18n 是一个应该只包含 3 列的表:id、locale 和 text。表parent 有一个列text(如果只有一个字段需要i18n,否则更多列)包含来自i18n.id 的值。我在 Parent 类中尝试了以下映射:
@ElementCollection @CollectionTable(name="i18n", joinColumns = @JoinColumn(referencedColumnName="id"))
@MapKeyColumn(name="locale") @Column(name="text")
public Map<String, String> text = newHashMap();
当禁用 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
我怎样才能摆脱这个额外的列?是否可以避免从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
}
【问题讨论】:
-
parent_id 字段有什么不必要的?您的元素集合需要某种方式将生成的表中的行与父实体(外键)相关联。也许展示您希望数据库的外观,有人可以帮助您弄清楚如何将实体映射到它。
-
我添加了所需的数据库描述。我需要一个可重复使用的 i18n 表来处理来自父级的一对多关系。我需要能够使用同一个 i18n 表来存储其他字段的翻译。 Parent.text & i18n.id 应该是将生成的表中的行与父实体相关联的方式。外键约束可能只存在于 parent.text。
-
你能展示完整的
i18n类吗? -
没有 i18n 类。 @ElementCollection 不需要它。
-
MapkeyColumn 不是你想象的那样,因为映射键是键值所独有的。您可以使用“区域设置”的映射键,创建一个以区域设置为键的文本映射。如果您的 i18n 表只使用 ID 值 99 而不是添加新的任意“文本”字段,那么问题是什么?这些文本不应该在实体之间共享,是吗?如果要重用它们,您确实应该将它们设为实体,使用 id+locale 作为复合 pk。 JPA 不允许对外键使用部分值,但 Hibernate 和其他提供者可能有办法映射“文本”-> id。
标签: java hibernate jpa internationalization