query patron example ejemplos ejemplo criteriabuilder java jpa-2.0 jpql criteria-api

java - patron - jpa query



Criterios JPA 2 con 3 tablas (3)

Estoy intentando crear un criterio para recuperar algunos objetos de 3 tablas (Asociado, Actualización y Detalle). Un Detalle tiene referencia a Asociado y Actualización, y una Actualización tiene referencia a una lista de Detalles. Mi objetivo es recuperar una lista de Actualizaciones que tenga al menos un Detalle con valor nulo en un campo específico, dado un ID de Asociado. En JPQL fue fácil de hacer pero el cliente dijo que esto debe estar codificado con criterios.

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

Intenté lo siguiente, pero acaba de devolver 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 puede ayudarme? Busqué pero no encuentro ningún ejemplo con 3 entidades.


Cada combinación lo lleva del parámetro de tipo izquierdista al derecho. Por lo tanto, la combinación de details de mi código (segunda línea) comienza desde fromUpdates , que es una Path<Update> , y crea algo que está detrás de la escena también una Path<Detail> . A partir de eso, puedes construir otras uniones. Prueba esto (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) );


Echa un vistazo a esta prueba con más de tres tablas. También use un metamodelo estático en lugar de usar nombres de atributos directos.

@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"))); }


Para las tres mesas involucradas.

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

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

}