Nuestros desarrolladores estrellas agotaron sus reservas de café, por su búsqueda todo el tiempo por la respuesta, hasta que Linda halló el hallazgo en Bitbucket así que ahora la comparte aquí.
Solución:
No puede unir directamente una columna en un predicado, pero puede crear expresiones any() como esta
QPerson.person.attributes.any().attributeValue.eq("X")
Este enfoque tiene la restricción de que la expresión de unión QPerson.person.attributes.any()
se puede utilizar en un solo filtro. Sin embargo, tiene la ventaja de que esta expresión se convierte internamente en una subconsulta que no entra en conflicto con la paginación.
Para restricciones múltiples, deberá construir una expresión de subconsulta explícitamente como esta
QPersonAttribute attribute = QPersonAttribute.personAttribute;
new JPASubQuery().from(attribute)
.where(attribute.in(person.attributes),
attribute.attributeName().name.toLowerCase().eq("eye color"),
attribute.attributeValue.toLowerCase().eq("blue"))
.exists()
Además de QueryDslPredicateExecutor
también puede usar consultas Querydsl a través de Spring Data como esta
public class CustomerRepositoryImpl
extends QuerydslRepositorySupport
implements CustomerRepositoryCustom
public Iterable findAllLongtermCustomersWithBirthday()
QCustomer customer = QCustomer.customer;
return from(customer)
.where(hasBirthday().and(isLongTermCustomer()))
.list(customer);
Ejemplo tomado de aquí https://blog.42.nl/articles/spring-data-jpa-with-querydsl-repositories-made-easy/
Para realizar consultas más complejas, he creado mi personalizado QueryDslRepository
con soporte de consultas JPQL y paginación JPA de datos de primavera.
Interfaz:
public interface QueryDslRepository
Page findAll(JPQLQuery jpqlQuery, Pageable pageable);
Implementación:
@Repository
public class QueryDslRepositoryImpl implements QueryDslRepository
@PersistenceContext
private EntityManager entityManager;
@Override
@SuppressWarnings("unchecked")
public Page findAll(JPQLQuery jpqlQuery, Pageable pageable)
Assert.notNull(jpqlQuery, "JPQLQuery must not be null!");
Assert.notNull(pageable, "Pageable must not be null!");
Querydsl querydsl = new Querydsl(entityManager, new PathBuilderFactory()
.create(jpqlQuery.getType()));
JPQLQuery countQuery = ((AbstractJPAQuery) jpqlQuery).clone(entityManager);
AbstractJPAQuery query = (AbstractJPAQuery) querydsl.applyPagination(pageable, jpqlQuery);
return PageableExecutionUtils.getPage(
// Clone query in order to provide entity manager instance.
query.clone(entityManager).fetch(),
pageable,
countQuery::fetchCount);
Ejemplo de uso:
@Repository
public interface CustomerRepository extends JpaRepository, QueryDslRepository,
QuerydslPredicateExecutor
Invocación real del repositorio:
BooleanBuilder predicates = new BooleanBuilder();
predicates = predicates.and(QCustomer.customer.active.eq(true));
JPQLQuery q = new JPAQuery()
.select(QCustomer.customer)
// You can use .join() method here.
.where(predicates);
Page result = customerRepository.findAll(q, Pageable.unpaged());