2016-11-04 82 views
0

我们有2个Entites:一个员工讲一组语言和一个员工进行的评论。将枚举的ElementCollections与QueryDSL和Hibernate进行比较

@Entity 
public class Employee { 

    @ElementCollection 
    @CollectionTable(name = "employeeLanguage" 
    @Column(name = "language") 
    @Enumerated(EnumType.String) 
    private Set<Language> languages; 
} 

@Entity 
public class Review { 

    @ManyToOne(fetch = FetchType.LAZY) 
    private Employee reviewer; 
} 

语言是一种简单枚举:

public enum Language { 
    DE, 
    EN, 
    ; 
} 

现在我们要查询的评论的特定子集,如果他们有一个特定员工的语言已经完全覆盖。 (在specificReviewsSubset所有Review.reviewer.languages的联合包含所有specificEmployee.languages)

我们用下面的查询尝试这样的:

private BooleanExpression hasAllEmployeeLanguagesCovered (List<Review> reviews, Employee employee) { 
    return new JPASubQuery().from(e) 
     .where(e.eq(employee)) 
     .where(e.languages.any().in(
      new JPASubQuery().from(r).join(r.reviewer, e) 
       .where(r.in(reviews)).distinct().list(e.languages.any() 
     ) 
     .exists(); 
} 

但我们得到以下错误:

java.lang.IllegalArgumentException: Undeclared path 'e_languages_ed0e7'. 
Add this path as a source to the query to be able to reference it. 

我们如何将e_languages添加到路径中? Afaik只有在我们拥有一个Q语言并在e.languages上加入语言时才有效。我们可以通过在语言中添加@Embeddable来生成这个,但是然后hibernate抱怨Language上缺少一个没有参数的构造函数。

回答

0

到目前为止,我们发现的唯一解决方法是剔除@ElementCollection,而不是引入EmployeeLanguage实体,该实体只持有对员工的引用和单个枚举值。此代码产生相同的DB模式作为一个与差的问题,现在查询语言是可能的:

private BooleanExpression hasAllEmployeeLanguagesCovered (List<Review> reviews, Employee employee) { 
    return new JPASubQuery().from(el) 
     .where(el.employee.eq(employee)) 
     .where(el.language.notIn(
      new JPASubQuery().from(r).join(r.reviewer, e).join(e.languages, el) 
       .where(r.in(reviews)).list(el.language) 
     ) 
     .notExists(); 

}

@Entity 
public class Employee { 

    @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL) 
    @Column(nullable = false) 
    @Getter @Setter 
    private Set<EmployeeLanguage> languages; 
} 

@Entity 
public class EmployeeLanguage implements Serializable { 

    @Id 
    @ManyToOne(fetch = FetchType.LAZY) 
    @Getter @Setter 
    private Employee employee; 

    @Id 
    @Column(nullable=false) 
    @Enumerated(EnumType.STRING) 
    @Getter @Setter 
    private Language language; 
} 

现在这个查询小改制后的作品