如何将I18n实现为JPA或Hibernate实体的JSON对象? [英] How can I implement I18n as a JSON object for a JPA or Hibernate entity?
问题描述
我有一个使用JPA
和Hibernate
的Spring-boot
应用程序.您可以在 GitHub存储库上找到整个代码.
I have a Spring-boot
application that uses JPA
and Hibernate
. You can find the whole code on this GitHub repository.
我的问题是如何使用JSON
结构如何在没有任何外键的情况下向特定列添加国际化功能?
My question is how can I add internationalization functionality to a specific column without any foreign keys and by using JSON
structure?
例如,我想这样定义一个JPA实体:
For example I would like to define a JPA entity like this:
@Entity
class Book {
@Id
private int id;
private Author author;
@I18n //<- this annotation is something that I am looking for
private String title;
}
,然后将title
列中的数据存储为en
和de
区域设置,如下所示:
and then the data in title
column would be stored like the following for en
and de
locales:
{"en":"Cologne","de":"Köln"}
然后,当当前语言环境是de
时,Köln
并且当en
被设置为语言环境时,Cologne
会在读取数据时获取!
And then when the current locale is de
the Köln
and when the en
is set as locale then Cologne
fetch in the time of reading data!
另外,当我们存储数据时,传递的字符串以JSON格式存储在相关属性中.例如,如果将语言环境设置为es
,并且用户通过了Kolne
,则我们必须在数据库中具有以下数据:
Also when we store the data, the passed string is stored in the relevant property in the JSON format. For example if the locale is set to es
and user passes Kolne
then we have to have the following data in the DB:
{"en":"Cologne","de":"Köln","es":"Kolne"}
对我来说很有趣的是,网络上用于hibernate和JPA的大多数解决方案都是基于我们拥有languages
和translations
表的旧方法.像此处或此处.
It is interesting for me that most of the solutions in the web for hibernate and JPA is based on an old method that we have languages
and translations
tables. Something like here or here.
但是我正在寻找的是一些解决方案,例如这,这是为Laravel建议的并完全按照我的说明存储翻译(即在JSON对象和同一列中)!
However what I am looking for is some solutions like this one which is suggested for Laravel and store the translations exactly in the way that I explained (i.e. in a JSON object and in the same column)!
我发现的唯一可能与之相关的解决方案(不是100%)是这一个 ,但是当我尝试对其进行测试时它不起作用,并且似乎不再受支持!
The only solution that I found and could be somehow relevant (Not 100%) is this one, however it does not working when I tried to test it and it seems does not supported anymore!
推荐答案
After some weeks I could return back again to my olingo2 odata server project.
我想做的比我预期的要简单.
What I wanted to do was simpler than what I expected.
Vlad Mihalcea 提出了解决方案,我对此表示赞赏,但是正如我在我需要一个在Olingo JPA库之外还可以使用的解决方案!但是,建议的解决方案存在Olingo无法处理JsonBinaryType
的问题.
The solution has been suggested by Vlad Mihalcea is good and I appreciate it, however as I mentioned in the question I need a solution that works beside of the Olingo JPA library! However, the suggested solution has this problem that Olingo cannot handle JsonBinaryType
.
这是我建议除Olingo JPA之外实施国际化的方法.
Here is my suggestion for implementing internationalization beside of Olingo JPA.
假设我们有一个像这样的BasicModel.java
:
Assume we have a BasicModel.java
like this:
import java.io.Serializable;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import java.io.IOException;
public abstract class BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
private static ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("unchecked")
protected static Map<String, String> jsonToMap(String json) {
Map<String, String> map = new HashMap<>();
try {
// convert JSON string to Map
if (json != null) {
map = (Map<String, String>) mapper.readValue(json, Map.class);
}
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
protected static String mapToJson(Map<String, String> map) {
String json = "";
try {
// convert map to JSON string
json = mapper.writeValueAsString(map);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
}
protected static String getLang() {
Locale currentLocale = LocaleContextHolder.getLocale();
String[] localeStrings = (currentLocale.getLanguage().split("[-_]+"));
return localeStrings.length > 0 ? localeStrings[0] : "en";
}
}
此类为我们提供了一种将JSON字符串转换为Map以及反之亦然的机制.
This class provides a mechanism for us to convert JSON strings to Map and vice versa.
The code for converters had been adapted from here. For using this snippet of code we need to add this maven dependency:
<!-- Convert JSON string to Map -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
最后,每当在JPA实体模型中,我们想要对字符串属性使用i18n
时,我们只需要稍微修改setter和getter方法即可.例如:
Finally, whenever in a JPA entity model we want to have i18n
for a string property we only need to modify setter and getter methods slightly. For example:
import javax.persistence.*;
import java.util.Map;
import java.util.Set;
/**
* The persistent class for the actions database table.
*
*/
@Entity
@Table(name = "actions")
@NamedQuery(name = "Action.findAll", query = "SELECT a FROM Action a")
public class Action extends BaseModel {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "id", unique = true, nullable = false, length = 255)
private String id;
@Column(nullable = false, length = 255)
private String name;
public Action() {
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
Map<String, String> map = jsonToMap(this.name);
return map.get(getLang());
}
public void setName(String name) {
Map<String, String> map = jsonToMap(this.name);
map.put(getLang(), name);
this.name = mapToJson(map);
}
}
这篇关于如何将I18n实现为JPA或Hibernate实体的JSON对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!