SlandShow
@SlandShow
70% of my body is made of movies.

Как сделать двойной join в criteria api?

У меня есть следующая картина.

Имеется 3 таблицы: 5c234b476d080426225192.jpeg

И так-же у меня есть RequestDTO, которая подаётся в параметры endpoint'а, чтобы обеспечить поиск из Бд по критериям.

Так выглядит сама DTO:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class RequestAssuranceAccessLine {

    @Pattern(regexp =  LINE_ID)
    private String lineId;

    @Min(0) @Max(31)
    private Integer ontId;

    private Technology technology;

    @Size(max = 50)
    private String ontSerialNumber;

    @ApiParam(allowEmptyValue = true)
    public RequestAssuranceAccessLine setLineId(String lineId) {
        this.lineId = lineId;
        return this;
    }

    @ApiParam(allowEmptyValue = true)
    public RequestAssuranceAccessLine setOntId(Integer ontId) {
        this.ontId = ontId;
        return this;
    }

    @ApiParam(allowEmptyValue = true)
    public RequestAssuranceAccessLine setTechnology(Technology technology) {
        this.technology = technology;
        return this;
    }

    @ApiParam(allowEmptyValue = true)
    public RequestAssuranceAccessLine setOntSerialNumber(String ontSerialNumber) {
        this.ontSerialNumber = ontSerialNumber;
        return this;
    }

}


ontId и ontSerialNumber находятся в двух разных таблицах.

Чтобы достать ontId, я делаю следующий JOIN через критерию:
// Join and predicate ontId from Default NeProfile
            Optional.ofNullable(requestAssuranceAccessLine.getOntId()).ifPresent(ontId -> {
                        Join<DefaultNeProfile, AccessLine> joinedDefaultNeProfile = root.join("defaultNeProfile");
                        predicates.add(criteriaBuilder.equal(joinedDefaultNeProfile.get("ontId"), ontId));
                    }
            );


Но чтобы мне вытащить ontSerialNumber, придётся лезть в таблицу B, и из этой таблицы B джойнить C.

Как же мне это сделать, если текущий criteria выглядит так:
public static Specification<AccessLine> criteriaForAccessLine(RequestAssuranceAccessLine requestAssuranceAccessLine) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();

            // Predicate lineId
            Optional.ofNullable(requestAssuranceAccessLine.getLineId()).ifPresent(lineId -> predicates.add(criteriaBuilder.equal(root.get("lineId"), lineId)));

            // Join and predicate ontId from Default NeProfile
            Optional.ofNullable(requestAssuranceAccessLine.getOntId()).ifPresent(ontId -> {
                        Join<DefaultNeProfile, AccessLine> joinedDefaultNeProfile = root.join("defaultNeProfile");
                        predicates.add(criteriaBuilder.equal(joinedDefaultNeProfile.get("ontId"), ontId));
                    }
            );

            // Predicate technology
            Optional.ofNullable(requestAssuranceAccessLine.getTechnology()).ifPresent(technology -> predicates.add(criteriaBuilder.equal(root.get("technology"), technology)));
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }
  • Вопрос задан
  • 2627 просмотров
Решения вопроса 1
SlandShow
@SlandShow Автор вопроса
70% of my body is made of movies.
решил.

Сначала джойню A <- B, поотом B <- C

// Join and predicate ontSerialNumber from Subscriber NeProfile 
            Optional.ofNullable(requestAssuranceAccessLine.getOntSerialNumber()).ifPresent(ontSerialNumber -> {
                        Join<DefaultNeProfile, AccessLine> joinedDefaultNeProfile = root.join("defaultNeProfile");
                        Join<SubscriberNeProfile, DefaultNeProfile> joinedSubscriberNeProfile = joinedDefaultNeProfile.join("subscriberNeProfile");
                        predicates.add(criteriaBuilder.equal(joinedSubscriberNeProfile.get("ontSerialNumber"), ontSerialNumber));
                    }
            );
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы