2012-03-29 24 views
6

¿Alguien puede ayudarme a obtener la consulta de criterios JPA para la consulta JPA que se menciona a continuación?¿Cómo escribir esta consulta usando la consulta de Criterios JPA?

SELECT p,l FROM Person p 
LEFT JOIN Language l ON (p.language = l.language and l.locale like :locale) 
AND p.name like :name 
AND p.time BETWEEN :startDate 
AND :endDate order by name asc 
+0

¿Puede mostrar sus implementaciones para Persona e idioma? –

Respuesta

10

Suponiendo que la persona tiene una relación con el lenguaje aquí es lo que haría en hibernación mayores:

Criteria criteria = entityManager.createCriteria(Person.class); 
Criteria languageCriteria = criteria.createCriteria("language"); 

languageCriteria.add(Restrictions.like("locale", locale)); 

criteria.add(Restrictions.like("name", name)); 
criteria.add(Restrictions.between("time", startDate, endDate)); 

criteria.addOrder(Order.asc("name")); 

y mi primer intento en JPA 2.0:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate conjunction = builder.conjunction(); 

criteria.where(builder.and(
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Por favor, hágamelo saber si eso funciona para ti.

Editar: Consulta actualizada para usar solo una llamada where.

+4

Las restricciones no forman parte de las especificaciones de JPA, es una función de Hibernación – perissf

+0

Tiene razón, necesito traducir a JPA 2 –

+0

Hola, en primer lugar, gracias, debería haber puesto esto en la pregunta. No existe ** relación ** b/w entre las entidades persona e idioma. Tanto la persona como el idioma tienen una columna en común (idioma (varchar)) con la que me estoy uniendo. lo que me está causando el problema es que tengo que hacer ** AJUSTE EXTERIOR IZQUIERDO ** para que, si no hay datos de idioma disponibles para la persona, aún así pueda obtener los datos de la persona con el objeto de lenguaje como nulo . – user1300877

6

Aunque la respuesta dada por johncarl fue aceptada, no me parece correcta. Los JavaDocs para CriteriaQuery.where (dicen):

modificar la consulta para restringir el resultado de la consulta según la expresión booleana especificada. Reemplaza la (s) restricción (es) previamente agregada, si corresponde.

lo que tengo entendido, cada una de las siguientes líneas (dando restricciones) anulará las restricciones dadas anteriormente:

criteria.where(builder.like(langJoin.get(Language_.locale), locale)); 
criteria.where(builder.like(pRoot.get(Person_.name), name)); 
criteria.where(builder.between(pRoot.get(Person_.time), startDate, endDate)); 

Esto significa que al final sólo la última restricción (entre el inicio y la fecha de finalización) quedaría.

Yo sugiero threfore siguientes modificaciones a la respuesta de johncarl:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate[] restrictions = new Predicate[] { 
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate) 
}; 

criteria.where(builder.and(restrictions)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Sin embargo, este código se ve muy feo! ¡Por favor, siéntase libre de editar si está mal y coméntelo si ve una mejor solución! ¡Sería gracioso!

+0

Gracias por tu pista. criteria.where (...) no se puede utilizar de forma incremental, ya que reemplaza los criterios potencialmente aprobados antes por completo. en el otro lado, funciona una sola cuestión de builder.and ("array of where predicates"). Gran solución, pho312 :) – Hartmut

+0

¡Gracias por una gran sugerencia! Me encantó tu enfoque. Simplemente agregaría que uno puede hacer una ArrayList y simplemente agregar criterios a medida que surgen. Por otro lado, no sé por qué, pero pRoot.get (Person_.name) no funciona para mí. Anume Me sale un error con la sintaxis de Person_. – moldovean

Cuestiones relacionadas