java - 将多语言数据库设计转换为 JPA 实体

标签 java jpa jpql

我正在使用 Java 设计一个多语言系统,在研究寻找存储多本地化文本的最佳数据库模型的过程中,我偶然发现了 Vertabelo 的博客和这个精彩的设计,from here :

Database model

但是,由于项目中有很多对象需要本地化,因此我避免自己编写所有 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/

相关文章:

java - id字段以外的自增字段如何实现?

java - 具有 persistence.xml 和属性映射的 JPA EntityManagerFactory

java - 今天的jpql日期比较

java - 连接非实体类中的两个实体

javascript - 可以从 JS 客户端获取 POST 请求的 Java 服务器

java - 用于高效浅克隆的哈希集实现或技术?

java - wait/notify 和 Condition 如何管理线程

java - 返回 200 响应代码而不是 204

jpa - 删除 JPA (FK) 中的一行

java - 无法对 JPQL 中的列进行 ORDER BY