JPA类别 - 语言关系

时间:2012-10-18 10:32:03

标签: hibernate jpa eclipselink

我正在使用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;

CategoryLanguage:

@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中使用“加入 ”,可以吗?

2 个答案:

答案 0 :(得分:1)

您的查询要求完整的类别实体,因此您无法严格按照JPA完成所需的操作。 JPA要求返回的类别实体反映数据库中的数据 - 这包括所有CategoryLanguages,无论它们在选择查询中可能对应的语言如何。

您可能想要做的是以不同方式重新排列查询。在这种情况下,查询与所需语言关联的CategoryLanguage实体,然后使用它来获取类别。仍将填充category-&gt; CategoryLanguage关系,但您的查询仅返回表示您想要的语言的CategoryLanguage,而不使用任何其他语言。按类别键入这些,以便在需要时更轻松。

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

答案 1 :(得分: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();