簡體   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