我正在使用 Java 设计一个多语言系统,在研究寻找存储多本地化文本的最佳数据库模型的过程中,我偶然发现了 Vertabelo 的博客和这个精彩的设计,from here :
但是,由于项目中有很多对象需要本地化,因此我避免自己编写所有 Dao,并尽可能坚持使用 JPA。
问题是我对 JPA 还不太了解,所以我在 google 上搜索了这个问题的可用解决方案,并找到了另一篇很棒的博客文章(幸运的是,它解决了 Vertabelo 博客中显示的相同设计: https://thoughts-on-java.org/localized-data-hibernate/ )
@Entity
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class LocalizedProduct {
@EmbeddedId
private LocalizedId localizedId;
@ManyToOne
@MapsId("id")
@JoinColumn(name = "id")
private Product product;
private String name;
private String description;
...
}
@Embeddable
public class LocalizedId implements Serializable {
private static final long serialVersionUID = 1089196571270403924L;
private Long id;
private String locale;
public LocalizedId() {
}
public LocalizedId(String locale) {
this.locale = locale;
}
// getter and setter methods ...
{
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Version
private int version;
@ManyToOne(fetch = FetchType.LAZY)
private Supplier supplier;
private Double price;
@OneToMany(mappedBy = "product", cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, orphanRemoval = true)
@MapKey(name = "localizedId.locale")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
private Map<String, LocalizedProduct> localizations = new HashMap<>();
...
public String getName(String locale) {
return localizations.get(locale).getName();
}
public String getDescription(String locale) {
return localizations.get(locale).getDescription();
}
}
Product p = new Product();
p.setPrice(19.99D);
LocalizedProduct lpDe = new LocalizedProduct();
lpDe.setId(new LocalizedId("de"));
lpDe.setProduct(p);
lpDe.setName("Hibernate Tips - Mehr als 70 Lösungen für typische Hibernateprobleme");
p.getLocalizations().put("de", lpDe);
LocalizedProduct lpEn = new LocalizedProduct();
lpEn.setId(new LocalizedId("en"));
lpEn.setProduct(p);
lpEn.setName("Hibernate Tips - More than 70 solution to common Hibernate problems");
p.getLocalizations().put("en", lpEn);
em.persist(p);
接下来就是我要解决的问题了。
“thoughts-on java”中提出的解决方案检索一个包含 map 的对象,其中包含附加的所有语言的所有翻译,这种行为是不需要的,因为我的系统将以至少 104 种语言呈现数据,最终。
问题是:是否有办法调整此解决方案,以便能够查询传递实体 id 和区域设置 id 的对象,并一次将翻译后的对象获取为一种语言?
最佳答案
对于可能的变体,以下是最简单/简洁的:
class Product {
long id;
InternationalText name;
InternationalText description;
}
class InternationalText {
long id;
}
class LocalizedText {
long id;
InternationalText international;
Locale locale;
String text;
}
由于实际上并不需要 InternationalText,因此不需要 List<LocalizedText>
ONE_TO_MANY 字段。加载 product.name
您不想加载所有语言。
我将详细信息留给您,因为您应该在单独的原型(prototype)中尝试一下;处理所有细节;如何做事。调试事情确实是延迟加载的等等。
关于java - 将多语言数据库设计转换为 JPA 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59976400/