我正在使用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中使用“加入 ”,可以吗?
答案 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();