1

我正在使用 JPA/Hibernate + Spring 构建基于类别的 Web 应用程序多语言

我目前构建了这三个 bean/实体:Category、CategoryLanguage 和 Language。

类别:

@Entity
public class Category implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @ManyToOne
    private Category father;
    @OneToMany(mappedBy = "father")
    private List<Category> children;
    @OneToMany(mappedBy="category")
    private List<CategoryLanguage> categoryLanguages;

类别语言:

@Entity
public class CategoryLanguage implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @ManyToOne
    Category category;
    @Column(length = 20, nullable = false)
    private String name;
    @ManyToOne
    private Language language;

语言

public class Language implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(length=2)
    private String id; // en, de, fr, it, es,...
    
    @Column(length=25)
    private String name; // English, Deutsch, Français,...

通过调用

from Category c join c.categoryLanguages cl where c.father = null and cl.language.id = :lang

它返回具有正确语言的第一级类别,但包含所有语言作为子语言。

为每种语言提取儿童,而不是我在查询中选择的语言。

我能做些什么来解决这个问题?我不能在 JPQL 中使用“join on ”,可以吗?

4

2 回答 2

1

您的查询要求提供完整的类别实体,因此您无法使用 JPA 严格完成您想要的。JPA 要求返回的类别实体反映数据库中的数据 - 这包括所有 CategoryLanguages,无论它们在选择查询中可能对应于哪种语言。

您可能想要做的是以不同的方式重新排列查询。在这种情况下,查询与所需语言关联的 CategoryLanguage 实体,然后使用它来获取 Category。category->CategoryLanguage 关系仍将被填充,但您的查询仅返回表示您想要的语言的 CategoryLanguage 而没有任何其他语言。如果需要,请按类别键入这些内容以使其更容易。

大多数提供程序确实允许直接向映射添加过滤条件,或者您甚至可以使用仅返回部分实体的查询,但我提醒您避免走这条路。一旦这样做,就很难正确维护应用程序和管理数据,并且最终可能会限制缓存等性能选项。例如,一旦您拥有所有部分类别实体并想要添加新的 CategoryLanguage 或进行任何其他更改,您如何处理它?合并不起作用,因为它会导致任何 CategoryLanguage 不在数据库列表中

于 2012-10-19T17:29:39.937 回答
0

确保使用FetchType.EAGER

使用如下:

SELECT c FROM Cagegory c INNER JOIN c.categoryLanguages l WHERE c.father = null AND l.id = :languageId

@OneToMany(mappedBy = "father", fetch = FetchType.EAGER)
private List<Category> children = new ArrayList();
@OneToMany(mappedBy="category", fetch = FetchType.EAGER)
private List<CategoryLanguage> categoryLanguages = new ArrayList();
于 2012-10-19T07:12:32.947 回答