Как в Querydsl для Spring Data JPA найти права, у которых хотя бы один дочерний элемент удовлетворяет нескольким условиям? - PullRequest
0 голосов
/ 14 марта 2020

У меня есть следующие отношения как часть моей модели:

enter image description here

Я пытаюсь использовать функциональность Querydsl в Spring Data JPA, чтобы найти все задания, в которых учащийся имеет арендный договор в данном месте жительства в пределах указанного диапазона дат. Я попробовал следующее, чтобы вернуть соответствующие BooleanExpression, которые можно объединить с другими и передать в 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));
}

Однако полученный SQL содержит независимые подзапросы EXISTS для каждого из трех условий: место жительства, дата начала и окончания; то есть в каждом конкретном случае каждое условие может быть удовлетворено другой арендной платой, в то время как то, что я хочу, состоит в том, чтобы квалифицируемая арендная плата удовлетворяла всем трем условиям. Я понимаю, что, вероятно, неправильно понял цель any() и подозреваю, что мне нужно использовать подзапросы Querydsl, но я не совсем уверен, как это сделать, тем более что некоторые примеры, которые я нашел, относятся к версии 3, и вещи, похоже, изменились в версии 4.

1 Ответ

0 голосов
/ 17 марта 2020

Это то, что мне удалось придумать для использования подзапросов в Querydsl 4. Сгенерированный SQL имеет только один подзапрос EXISTS, который проверяет все три условия.

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