2016-11-04 20 views
0

2つのエンティティがあります。一連の言語を話す従業員と従業員によって実行されるレビューです。列挙型の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は、私たちがQLanguageを持っていて、e.languagesで言語に参加する場合にのみ動作します。 @EmbeddableをLanguageに追加することでこれを生成することができましたが、その後、休止状態でLanguageのArgsコンストラクターが見つからないという不満がありました。

答えて

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

今、このクエリは、小さな再編後に動作します

関連する問題