2013-12-05 9 views
5

Wie erstelle ich eine effiziente JPA-Kriterienabfrage, um nur dann eine Liste von Entitäten auszuwählen, wenn sie in einer Join-Tabelle vorhanden sind? Zum Beispiel nehmen die folgenden drei Tabellen:JPA-Kriterienunterabfrage auf JoinTable

create table user (user_id int, lastname varchar(64)); 
create table workgroup (workgroup_id int, name varchar(64)); 
create table user_workgroup (user_id int, workgroup_id int); -- Join Table 

Die Abfrage in Frage (was ich JPA produzieren wollen) ist:

select * from user where user_id in (select user_id from user_workgroup where workgroup_id = ?); 

die folgenden Kriterien Abfrage wird ein ähnliches Ergebnis produzieren, aber mit zwei verbindet :

CriteriaBuilder cb = getEntityManager().getCriteriaBuilder(); 
    CriteriaQuery<User> cq = cb.createQuery(User.class); 
    Root<User> root = cq.from(User.class); 
    cq.select(root); 

    Subquery<Long> subquery = cq.subquery(Long.class); 
    Root<User> subroot = subquery.from(User.class); 
    subquery.select(subroot.<Long>get("userId")); 
    Join<User, Workgroup> workgroupList = subroot.join("workgroupList"); 
    subquery.where(cb.equal(workgroupList.get("workgroupId"), ?)); 
    cq.where(cb.in(root.get("userId")).value(subquery)); 

    getEntityManager().createQuery(cq).getResultList(); 

Das grundlegende Problem scheint zu sein, dass ich die @JoinTable Anmerkung für die USER_WORKGROUP bin mit Join-Tabelle anstelle eines separaten @Entity für den Tisch kommen, damit es nicht scheint Ich kann USER_WORKGROUP als Root in einer Kriterienabfrage verwenden.

Hier sind die Entitätsklassen:

@Entity 
public class User { 
    @Id 
    @Column(name = "USER_ID") 
    private Long userId; 
    @Column(name = "LASTNAME") 
    private String lastname; 
    @ManyToMany(mappedBy = "userList") 
    private List<Workgroup> workgroupList; 
} 

@Entity 
public class Workgroup { 
    @Id 
    @Column(name = "WORKGROUP_ID") 
    private Long workgroupId; 
    @Column(name = "NAME") 
    private String name; 
    @JoinTable(name = "USER_WORKGROUP", joinColumns = { 
     @JoinColumn(name = "WORKGROUP_ID", referencedColumnName = "WORKGROUP_ID", nullable = false)}, inverseJoinColumns = { 
     @JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID", nullable = false)}) 
    @ManyToMany 
    private List<User> userList; 
} 
+1

Können Sie uns Ihre '@ Entity' Klassen zeigen? –

+0

@Templar - Entity-Klassen hinzugefügt. – Ryan

Antwort

0

Soweit ich weiß, JPA ignoriert im Wesentlichen auf den Tisch kommen. Die JPQL, die Sie tun würden

select distinct u from user u join u.workgroupList wg where wg.name = :wgName 

für die Kriterien Abfrage sein, sollten Sie in der Lage zu tun:

Criteria c = session.createCriteria(User.class, "u"); 
c.createAlias("u.workgroupList", "wg"); 
c.add(Restrictions.eq("wg.name", groupName)); 
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

gibt es keine Notwendigkeit, über die Mitte Tisch kommen zu kümmern.

Verwandte Themen