Convert multilanguage database design into JPA entities

早过忘川 提交于 2020-03-04 23:00:24

问题


I am designing a multilanguage system using Java, and during my research to find the best database model to store multi-localized text, I came accross Vertabelo's blog and this wonderful design, from here:

Database model

However, as there are lots of objects to be localized in the project, I am avoiding to write all the Dao's myself, and stick with JPA, if possible.

The thing is that I don't know much of JPA yet, so I googled for available solutions to this problem, and found another great blog post (which fortunatelly addresses the same design shown in Vertabelo's blog here: 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);

Then comes the problem I wanna solve.

The solution presented in "thoughts-on java" retrieves an object holding a map with all translations from all languages attached in it, and this behavior is not desired, as my system is going to present data in at least 104 languages, eventually.

The question is: is there a way to tune this solution in order to be able to query for an object passing Entity id and Locale id and get a translated object to a single language at a time?


回答1:


For the possible variants, the following is simplest/concize:

class Product {
    long id;

    InternationalText name;
    InternationalText description;
}

class InternationalText {
    long id;
}

class LocalizedText {
    long id;

    InternationalText international;
    Locale locale;
    String text;
}

As the InternationalText is not really needed, it does not need a List<LocalizedText> ONE_TO_MANY field. On loading a product.name you do not want to load all languages.

I leave the details to you, as you should in a separate prototype try it out; work all details; how to do things. Debugging that things indeed are lazily loaded etcetera.



来源:https://stackoverflow.com/questions/59976400/convert-multilanguage-database-design-into-jpa-entities

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!