I have the following relationships as part of my model:
I am trying to use the Querydsl functionality in Spring Data JPA to find all engagements where the associated student has a tenancy in a given residence within a given date range. I tried the following to return the appropriate BooleanExpression
that could be combined with others and supplied to EngagementRepository.findAll()
:
public BooleanExpression inResidence(Residence residence, LocalDate startDate, LocalDate endDate) {
final QTenancy tenancies = QEngagement.engagement.student.tenancies.any();
return tenancies.residence.eq(residence)
.and(tenancies.startDate.loe(endDate))
.and(tenancies.endDate.goe(startDate));
}
However the resulting SQL contains independent EXISTS subqueries for each of the three conditions – residence, start date and end date; that is, as it stands each condition could be satisfied by a different tenancy when what I am after is for a qualifying tenancy to satisfy all three conditions. I realise I have probably misunderstood the purpose of any()
and suspect that I need to make use of Querydsl's subqueries, but I am not quite sure how to, especially since some examples I have found are for version 3 and things appear to have changed in version 4.
This is what I managed to come up with for using subqueries in Querydsl 4. The generated SQL has just one EXISTS subquery that tests all three conditions.
public BooleanExpression inResidence(Residence residence, LocalDate startDate, LocalDate endDate) {
final QTenancy tenancy = QTenancy.tenancy;
return QEngagement.engagement.student.tenancies.any().in(
JPAExpressions.selectFrom(tenancy).where(
tenancy.residence.eq(residence)
.and(tenancy.startDate.loe(endDate))
.and(tenancy.endDate.goe(startDate))
)
);
}