【问题标题】:Convert multilanguage database design into JPA entities将多语言数据库设计转换为 JPA 实体
【发布时间】:2020-01-29 22:15:28
【问题描述】:

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

Database model

但是,由于项目中有很多对象需要本地化,所以我避免自己编写所有的 Dao,如果可能的话,坚持使用 JPA。

问题是我对 JPA 了解不多,所以我搜索了这个问题的可用解决方案,并找到了另一篇很棒的博客文章(幸运的是,它解决了 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”中提出的解决方案检索一个对象,该对象包含一个地图,其中包含来自所有语言的所有翻译,并且这种行为是不希望的,因为我的系统将以至少 104 种语言呈现数据,最终。

问题是: 有没有办法调整这个解决方案,以便能够查询传递实体 id 和区域设置 id 的对象,并一次将翻译的对象翻译成一种语言?

【问题讨论】:

    标签: java jpa jpql


    【解决方案1】:

    对于可能的变体,以下是最简单/简洁的:

    class Product {
        long id;
    
        InternationalText name;
        InternationalText description;
    }
    
    class InternationalText {
        long id;
    }
    
    class LocalizedText {
        long id;
    
        InternationalText international;
        Locale locale;
        String text;
    }
    

    因为 InternationalText 并不是真正需要的,所以它不需要List&lt;LocalizedText&gt; ONE_TO_MANY 字段。在加载 product.name 时,您不想加载所有语言。

    我把细节留给你,你应该在一个单独的原型中尝试一下;处理所有细节;怎么做。调试确实是延迟加载等等。

    【讨论】:

    • 嗨@Joop,感谢您回答我的问题。不确定我是否理解您的变体,似乎所有实体最终都会将翻译存储在一个多语言表中,对吗?
    • 是的,那个变种。在某些方面并不完美。但最小的 w。河。吨。数据库架构。 P.S. 好名字很重要。
    • 是的,很好的输入。会给+1,但SO不会让我这样做,太新手了:P但问题是,在这个项目中,我宁愿坚持每个实体的翻译表,否则它会给我一个巨大的单表,这将更难维护。到目前为止,我将在下面回答我正在采用的方法。
    • 这也很好。尤其是我已经用类似方法做过的产品名称和描述。仍然可以编写可以维护文本、导入的通用代码。一件事:我还使用基于 xml 的翻译记忆库作为填充数据库的来源。假设您将某些特定语言的翻译外包出去。
    猜你喜欢
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 1970-01-01
    • 2010-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多