Criterios de JPA 2 con 3 tablas

Estoy tratando de crear un criterio para recuperar algunos de los objetos de 3 tablas (Asociado, Actualización y Detalle). Un Detalle que ha de referencia para Asociar y Actualización, y una Actualización hace referencia a una lista de Detalles. Mi objetivo es recuperar una lista de las Actualizaciones que tiene al menos un Detalle con valor null en un campo específico, dado un Asociado de identificación. En JPQL fue fácil de hacer, pero el cliente dijo que este debe ser codificado con criterio.

Mi JPQL fue:

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

He intentado de la siguiente, pero acaba de regresar todas las actualizaciones en la base de datos:

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

Alguien me puede ayudar? He buscado pero no se puede encontrar ningún ejemplo con 3 entidades.

OriginalEl autor Rafael Toledo | 2013-06-17

3 Kommentare

  1. 27

    Cada unirse lleva desde el leftish parámetro de tipo para la rightish uno. Así, el details unirse de mi código (segunda línea) comienza a partir de fromUpdates, que es un Path<Update>, y crea algo que está detrás de las escenas también un Path<Detail>. A partir de eso, usted puede construir otras combinaciones. Pruebe este (código no probado):

    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)
    );
    Trabajó como un encanto! Estos criterios se une me hizo loco, pero esto me ayudó mucho! Gracias perissf 🙂

    OriginalEl autor perissf

  2. 5

    Para tres tablas implicadas.

    CriteriaBuilder generador = theEntityManager.getCriteriaBuilder();
    CriteriaQuery consulta1 = 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();

    clase pública 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;
    }

    }

    Es el uso de múltiples condiciones como una instrucción sql con DONDE x=y Y a=b Y c=d …. O tengo que usar el «y(Predicado)» método para establecer que?
    es como una instrucción SQL con la cláusula where.

    OriginalEl autor Smart Coder

  3. 0

    Checkout esta prueba con más de tres tablas . También uso estático modelo meta en lugar de utilizar directa nombres de atributo.

        @Test
    @Rollback(false)
    @Transactional
    public void   
    fetch() {
        CriteriaBuilder cb = 
    entityManager.getCriteriaBuilder();
        CriteriaQuery<Instructor> cq = 
    cb.createQuery(Instructor.class);
        Root<Instructor> root = 
    cq.from(Instructor.class);
        root.join(Instructor_.idProof);
        root.join(Instructor_.vehicles);
        Join<Instructor, Student> insStuJoin = 
    root.join(Instructor_.students);
        insStuJoin.join(Student_.instructors);
        Join<Student, Vehicle> stuVehcileJoin.   
    = insStuJoin.join(Student_.vehicles);
        Join<Vehicle, Document> 
    vehicleDocumentJoin = 
    stuVehcileJoin.join(Vehicle_.documents);
    
    DataPrinters.
    listDataPrinter.accept.   
    (queryExecutor.fetchListForCriteriaQuery
          (cq.select(root).where
    (cb.greaterThan(root.get(Instructor_.id), 2),                        
               cb.in(vehicleDocumentJoin.get
                              (Document_.name)).value("1")
    .value("2").value("3")));
    }

    OriginalEl autor Vaneet Kataria

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea