2013-06-17 8 views
12

Sto provando a creare un criterio per recuperare alcuni oggetti da 3 tabelle (Associa, Aggiorna e Dettagli). Un dettaglio ha riferimento a Associare e aggiornare e un aggiornamento fa riferimento a un elenco di dettagli. Il mio obiettivo è quello di recuperare un elenco di aggiornamenti che ha almeno un dettaglio con valore null in un campo specificato, dato un ID associato. In JPQL è stato facile fare ma il cliente ha detto che questo deve essere codificato con criteri.Criteri JPA 2 con 3 tabelle

mio JPQL era:

public List<Update> getUpdates(long associateId) { 
    TypedQuery<Update> query = em.createQuery("select distinct u from Update u, Detail dt, Associate a " 
     + "where dt.update = u and dt.associate = a and a.associateId = :id and " 
     + "dt.ack_date is null", Update.class); 
    query.setParameter("id", associateId); 
    return query.getResultList(); 
} 

ho provato quanto segue, ma appena tornato tutti gli aggiornamenti nel database:

public List<Update> getUpdates(long associateId) { 
    CriteriaBuilder builder = em.getCriteriaBuilder(); 
    CriteriaQuery<Update> query = builder.createQuery(Update.class); 

    Root<Update> fromUpdates = query.from(Update.class); 
    Root<Associate> fromAssociate = query.from(Associate.class); 
    Root<Detail> fromDetail = query.from(Detail.class); 

    Join<Detail, Associate> associateJoin = fromDetail.join("associate"); 
    Join<Detail, Update> updateJoin = fromDetail.join("update"); 

    TypedQuery<Update> typedQuery = em.createQuery(query 

      .select(fromUpdates) 
      .where(builder.and(
        builder.equal(fromAssociate.get("associateId"), associateId), 
        builder.equal(fromDetail.get("associate"), associateJoin), 
        builder.equal(fromDetail.get("update"), updateJoin), 
        builder.isNull(fromDetail.get("ack_date")) 
      )) 

      .orderBy(builder.asc(fromUpdates.get("updateId"))) 
      .distinct(true) 
    ); 

    return typedQuery.getResultList(); 
} 

qualcuno mi può aiutare? Ho cercato ma non riesco a trovare alcun esempio con 3 entità.

risposta

22

Ogni join ti porta dal parametro di tipo sinistro a quello di destra. Pertanto, il join details del mio codice (seconda riga) inizia da fromUpdates, ovvero Path<Update> e crea qualcosa che è dietro le quinte anche a Path<Detail>. Da questo, puoi creare altri join. Prova questo (codice non testato):

Root<Update> fromUpdates = query.from(Update.class); 
Join<Update, Detail> details = fromUpdates.join("details"); 
Join<Detail, Associate> associate = details.join("associate"); 
List<Predicate> conditions = new ArrayList(); 
conditions.add(builder.equal(associate.get("associateId"), associateId)); 
conditions.add(builder.isNull(details.get("ack_date"))); 

TypedQuery<Update> typedQuery = em.createQuery(query 
     .select(fromUpdates) 
     .where(conditions.toArray(new Predicate[] {})) 
     .orderBy(builder.asc(fromUpdates.get("updateId"))) 
     .distinct(true) 
); 
+3

funzionato come un fascino! Questi criteri mi hanno fatto impazzire, ma questo ha aiutato molto! Grazie perissf :) –

1

Per tre tavoli coinvolti.

Builder CriteriaBuilder = theEntityManager.getCriteriaBuilder(); CriteriaQuery query1 = builder.createQuery (BasicMemberInfo.class);

Root<Table1> table1 = query1.from(Table1.class); 
    Root<Table2> table2 = query1.from(Table2.class); 
    Root<Table3> table3 = query1.from(Table3.class); 

    List<Predicate> conditions = new ArrayList(); 
    conditions.add(builder.equal(table3.get("Table1").get("memberId"), table1.get("memberId"))); 
    conditions.add(builder.equal(table2.get("tableid").get("memberId"), table1.get("memberId"))); 
    conditions.add(builder.equal(table2.get("indicator"), 'Y')); 
    conditions.add(builder.equal(table3.get("StatusCd"), "YES")); 

    TypedQuery<BasicCustInfo> typedQuery = theEntityManager.createQuery(
      query1.multiselect(table1.get("memberId"), table2.get("AcctId")) 
      .where(conditions.toArray(new Predicate[] {})) 
    ); 

    List<BasicMemberInfo> custList = typedQuery.getResultList(); 

public class BasicMemberInfo {

String memberId; 
String AcctId; 

public BasicCustInfo() { 
    // TODO Auto-generated constructor stub 
} 

public BasicMemberInfo(BigDecimal memberId,String AcctId) { 
    this.memberId = memberId; 
    this.AcctId = AcctId; 
} 

public BigDecimal getmemberId() { 
    return memberId; 
} 
public void setmemberId(BigDecimal memberId) { 
    memberId = memberId; 
} 
public String getAcctId() { 
    return AcctId; 
} 
public void setAcctId(String AcctId) { 
    AcctId = AcctId; 
} 

}