В моем проекте я использую Groovy с Spring Data JPA Specification
для создания запросов Hibernate.
Я не могу предоставить свои фактические запросы, но чтобы проиллюстрировать мою проблему, скажем, у меня есть объекты здания, и в каждом здании есть этажи, а на каждом этаже есть и комнаты, и окна.
Поведение, которое я пытаюсь смоделировать, похоже на этот собственный SQL-запрос:
SELECT b.*, r.*
FROM building b
INNER JOIN floor f ON b.id = f.building_id
INNER JOIN window w ON f.id = w.floor_id
LEFT OUTER JOIN room r ON f.id = r.floor_id
WHERE w.id = 1;
У меня есть спецификация, аналогичная приведенной ниже:
public class MySpec implements Specification<Building> {
@Override
public Predicate toPredicate(final Root<Building> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) {
final Join floorsJoin = root.join("floors");
final Join windowsJoin = floorsJoin.join("windows");
//I'd like to remove this line
final Fetch floorsFetch = root.fetch("floors"); // <---
floorsFetch.fetch("rooms", JoinType.LEFT);
cb.equal(windowsJoin.get("id"), 1L);
}
}
Строка, аннотированная выше, является моей проблемой. Если я оставлю его, сгенерированный запрос будет выглядеть примерно так:
SELECT b.*, f2.*, r.*
FROM building b
INNER JOIN floor f ON b.id = f.building_id
INNER JOIN window w ON f.id = w.floor_id
INNER JOIN floor f2 ON b.id = f2.building_id
LEFT OUTER JOIN room r ON f2.id = r.floor_id
WHERE w.id = 1;
(обратите внимание на дубликат INNER JOIN
из floor
и ненужные данные f2.*
)
Если я удалю его и вместо этого использую floorsJoin
для получения комнат, я получаю следующую ошибку Hibernate:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
Ненужные данные f2.*
были бы в порядке, за исключением того, что я не могу заменить приведенный выше floorsJoin
на floorsFetch
, потому что мне нужно присоединиться к таблице windows
(без извлечения windows
), а класс Fetch
не имеет метода .join
.
Мне трудно понять, как мне выполнить то, что мне нужно, при этом генерируя один запрос; конечно, я должен упустить что-то простое.
Любые мысли или советы, которые вы могли бы предоставить, будут высоко оценены.
Большое спасибо, БиДжей.