2013-12-05 22 views
5

Come si crea una query di criteri JPA efficiente per selezionare un elenco di entità solo se esistono in una tabella di join? Per esempio prendere le seguenti tre tabelle:Criteri JPA sottoquery su 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 

La query in questione (quello che voglio APP per la produzione) è:

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

La seguente query Criteri produrrà un risultato simile, ma con due giunzioni :

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

il problema fondamentale sembra essere che sto usando l'annotazione @JoinTable per l'USER_WORKGROUP join tabella anziché un @Entity separato per la tavola in modo da unire non sembra Posso usare USER_WORKGROUP come root in una query di criteri.

Qui ci sono le classi di entità:

@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

Puoi mostrarci le tue classi '@ Entity'? –

+0

@Templar - Aggiunte classi di entità. – Ryan

risposta

0

Per quanto ne so, JPA ignora essenzialmente la tabella di aderire. Il JPQL che si fa sarebbe

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

per la query criteri, si dovrebbe essere in grado di fare:

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

non c'è bisogno di preoccuparsi per la metà join tavolo.

Problemi correlati