繁体   English   中英

将枚举的ElementCollection与QueryDSL和Hibernate进行比较

[英]Comparing ElementCollections of enums with QueryDSL and Hibernate

我们有2个实体:一个会说多种语言的员工和一个由员工进行的审查。

@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仅在我们拥有QLanguage并在e.languages上加入语言时才有效。 我们可以通过在Language上添加@Embeddable来生成此函数,但随后休眠会抱怨在Language上缺少无参数的构造函数。

到目前为止,我们发现的唯一解决方法是抛弃@ElementCollection,而是引入一个EmployeeLanguage实体,该实体仅持有对雇员的引用和单个枚举值。 此代码产生的数据库模式与问题中的数据库模式相同,区别在于现在可以查询语言:

@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;
}

现在,此查询在进行少量重组后即可工作:

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();

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM