亲爱的Stackflow社区,
我希望将国际化字符串存储在我的实体中,而我正在努力解决这个问题。我将在这里描述我能想到的两个解决方案,并希望得到您的反馈。
在这个解决方案中,我的数据库中有以下表格:
skip
我总是使用以下方法访问此集合:
LabelId Language VALUE Entity Id
WELCOME_TEXT EN "..." Questionnaire 1
WELCOME_TEXT DE "..." Questionnaire 1
GOODBYE_TEXT EN "..." Questionnaire 1
GOODBYE_TEXT DE "..." Questionnaire 1
QUESTION_TITLE EN "..." Question 12
QUESTION_TITLE DE "..." Question 12
OPTION_NAME EN "..." Option 23
OPTION_NAME DE "..." Option 23
FACTOR_NAME EN "..." Factor 11
FACTOR_NAME DE "..." Factor 11
在此解决方案中,所有实体都将Map存储在同一个表中:
void setLabels(Entity entity, LabelId labelId, Map<String, String langValues)
Map<String, String> getLabels(Entity entity, LabelId labelId)
然后,我将按以下格式映射实体中的所有字段:
i18n.java:
LabelId Language VALUE questionnaire_id factor_id question_id option_id
WELCOME_TEXT EN "..." 1
WELCOME_TEXT DE "..." 1
GOODBYE_TEXT EN "..." 1
GOODBYE_TEXT DE "..." 1
QUESTION_TITLE EN "..." 12
QUESTION_TITLE DE "..." 12
OPTION_NAME EN "..." 23
OPTION_NAME DE "..." 23
FACTOR_NAME EN "..." 11
FACTOR_NAME DE "..." 11
Questionnaire.java:
@Entity
@Table(uniqueConstraints={@UniqueConstraint(columnNames={"label", "language", "questionnaire_id", "question_id", ... })})
public class i18n extends PersistentObject { // where it gets ID from
Label label; // enum
Language language; // enum
String value; // the actual text
// bi-directional links to the linked entities
@ManyToOne Questionnaire questionnaire;
@ManyToOne Question question;
...
}
Question.java:
@OneToMany(mappedBy = "questionnaire")
List<i18n> labels;
另一种简单的方法是简单地为每个属性存储这样的地图:
@OneToMany(mappedBy = "question")
List<i18n> labels;
此解决方案在我的数据库中创建了一个TON表,这将使查询和维护变得混乱。
第一个解决方案为我提供了一个更好的表格,代价是每次需要时都需要通过附加服务检索标签。 第二个解决方案使实体的代码保持干净,但SQL表格杂乱,所有需要翻译的实体都有许多列。
你会怎么做?有更好的解决方案吗?
提前感谢所有反馈!
答案 0 :(得分:1)
我们通过分离每个实体的翻译并保持规范化来解决这个问题,因此排除了主要实体的翻译,因此对于您的一个示例权利:
CREATE TABLE question(
id SERIAL PRIMARY KEY,
origin_date DATE; --Put all fields that don't change via language here
);
-- Create a translation table for the above entity and put all fields that
-- change through internationalization here for example name and description
CREATE TABLE question_translation(
id SERIAL PRIMARY KEY,
question_id int NOT NULL REFERENCES question(id),
language_id int NOT NULL REFERENCES language(id), --we have a separate table for languages so normalisation is provided
name TEXT,
description TEXT,
UNIQUE(question_id , language_id)
);
这两个表的示例数据现在是:
表格语言(例如):
id iso_a2_code
------------------
5 DE
12 EN
表格问题:
id date
----------------
1 19.04.2018
表格问题翻译:
id question_id language_id name description
---------------------------------------------------------
1 1 5 TestDE Description in DE
2 1 12 TestEN Description in EN
实体的JavaCode(未测试):
<强>问题:强>
@Entity
@Table(name = "question")
public class Question {
@Id
@Column
@NotNull
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
@OneToMany(mappedBy = "question", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<QuestionTranslation> questionTranslations = new HashSet<>();
@Column
@Convert(converter = LocalDateConverter.class)
private LocalDate date;
}
问题翻译:
@Entity
@Table(name = "question_translation")
public class QuestionTranslation {
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@Column
private String description;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH)
@JoinColumn(name = "question_id")
private Question question;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REFRESH)
@JoinColumn(name = "language_id")
private LanguageEntity language;
}
答案 1 :(得分:1)
我用所描述的第一种方法解决了这个问题。 另外,我使用PreparedStatements缓存了查询,并且它们的表现非常好。除了设置单个翻译之外,我还创建了批量编辑和批量检索方法,这些方法表现得更好。
答案 2 :(得分:-1)
这是我的解决方法-https://github.com/azerphoenix/spring-i18n-demo
您可以看一下这个演示项目。