Запрос JPA Critiera с множеством объединений с использованием трех предикатов OR - PullRequest
2 голосов
/ 19 октября 2011

Я пишу запрос, используя JPA Criteria API, где я хочу получить все поездки, соответствующие любому из этих предикатов:

  • Получить все путешествия (MasterTravels), которыми я владею (владелец = пользователь)
  • Получить все путешествия, где я пассажир (Пассажир, пользователь = пользователь)
  • Получить все поездки, к которым я подал заявку (MasterTravelApplication, пользователь = пользователь)

Первый предикат прост. Я просто проверяю, является ли владелец = пользователь в MasterTravel. Для второго предиката мне нужно присоединиться к MasterTravel-> MTT-> Travel-> Passenger и затем проверить, если Passenger_.user = user. Для третьего предиката мне нужно присоединиться в другом направлении MasterTravel-> MasterTravelApplication и проверить на наличие MasterTravelApplication_.user = user. Это то, что нарушает мой запрос, так как у меня первые два работают, но когда я пытаюсь добавить последний предикат, он перестает работать.

Должен ли я создать новый корень для последнего соединения или как я могу получить объединение соединений 1 и 2 ниже?

CriteriaQuery<MasterTravel> q = cb.createQuery(MasterTravel.class);
Root<MasterTravel> root = q.from(MasterTravel.class);

// Joins 1, these works fine
Join<MasterTravel, MTT> mtts = root.join(MasterTravel_.mtt);
Join<MTT, Travel> travels = mtts.join(MTT_.travel);
Join<Travel, Passenger> passengers = travels.join(Travel_.passengers);                      

// Joins 2, this doesn't work
Join<MasterTravel, MasterTravelApplication> application = root.join(MasterTravel_.applications);

Predicate p = cb.or(
    cb.equal(passengers.get(Passenger_.user), user), 
    cb.equal(root.get(MasterTravel_.owner), user),
    cb.equal(application.get(MasterTravelApplication_.user), user));  // When I add this it stops working

q.select(root);
q.where(p);         
q.orderBy(cb.desc(root.get(MasterTravel_.createdTimestamp)));                       
q.distinct(true);

List<MasterTravel> resultList = em.createQuery(q).getResultList();

1 Ответ

2 голосов
/ 19 октября 2011

Вы не описываете связи между сущностями, но я предполагаю, что мастер-путешествие не обязательно имеет хотя бы одно приложение, а поскольку вы выполняете внутреннее объединение, все мастер-путешествия, которые нени одного приложения не найдено.

Используйте метод join, принимая JoinType в качестве аргумента, и используйте JoinType.LEFT.

...