Saltar al contenido

Spring-Data-JPA con QueryDslPredicateExecutor y unirse a una colección

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

Aquí puedes ver las reseñas y valoraciones de los lectores

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *