Hibernate пользовательский SQL-запрос с соединением - избегая возврата списка массивов
У меня есть пользовательский SQL-запрос в Hibernate (3.5.2), в котором я хочу вернуть сопоставленный объект и связанный (объединенный) объект. Однако Hibernate, похоже, дает мне список массивов, а не список объектов.
Чтобы немного упростить мою ситуацию: -
Entity1 содержит внешний ключ Entity2, а сопоставленные объекты настроены так, что Entity1 имеет свойство объекта, ссылающееся на Entity2. Я хочу получить список объектов Entity1, но с уже инициализированной ссылкой на объект (чтобы связанный объект был загружен).
Теперь я могу сделать это с помощью специального SQL-запроса, например:
final SQLQuery qry = hibernateSession.createSQLQuery(
"select {entity1.*}, {entity2.*} from entity1 inner join entity2 on entity1.fk = entity2.id ");
qry.setReadOnly(true);
qry.addEntity("entity1", Entity1.class);
qry.addJoin("entity2", "entity1.entity2");
List list = qry.list(); // Returns list of arrays!!
Это работает, поскольку все объекты Entity1 правильно инициализируются. Однако список, который я возвращаю, НЕ является простым списком объектов Entity1. Это фактически список массивов, где каждый массив содержит 2 элемента - Entity1 и Entity2. Я предполагаю, что это потому, что я поставил две записи псевдонимов в предложение SELECT.
Если я удалю второй псевдоним (для Entity2), я просто получаю ошибки "столбец не найден" - предположительно потому, что Hibernate не может найти поля для инициализации объекта entity2.
Любые идеи? У меня есть запрос, который может возвращать поля для основного и связанного объекта, но я хочу, чтобы List возвращался только как список объектов Entity1.
Упреждающий комментарий: Да, я знаю, что я мог бы переструктурировать это и сделать запрос по-другому (критерии API и т.д.). Но это то, что я застрял в данный момент. В этой конкретной ситуации меня сдерживают некоторые другие факторы, поэтому я надеялся, что есть какой-то способ сообщить Hibernate, что я хочу!
Спасибо.
Ответы
Ответ 1
Здесь Entity 1 (child) содержит внешний ключ для Entity 2 (parent), в классе Entity1 (child) pojo должна быть переменная родительского типа.
Пусть это "E", теперь запрос будет:
Select ent1.* from Entity1 ent1 inner join ent1.E.id
Здесь id является первичным ключом Entity2
Ответ 2
У меня нет спящего режима передо мной, чтобы проверить, глядя на руководство спящего режима, похоже, это небольшое изменение:
final SQLQuery qry = hibernateSession.createSQLQuery(
"select {entity1.*} from Entity1Table entity1 inner join Entity2Table entity2 on entity1.fk = entity2.id ");
qry.setReadOnly(true);
qry.addEntity("entity1", Entity1.class);
qry.addJoin("entity1.entity2");
Это должно вернуть вам только объекты Entity1 с уже инициализированным свойством Entity2.
Если это не сработает, попробуйте заменить внутреннее соединение в SQL на предложение where, т.е.
select {entity1.*} from Entity1Table entity1, Entity2Table entity2 WHERE entity1.fk = entity2.id ");
Это синтаксически эквивалентно примеру, указанному в документах спящего режима.
Ответ 3
Посмотрите, может ли это помочь вам...
Ответ 4
Одним из способов может быть использование соединений Theta-Style:
select u from User u join u.permissions p where p.code = :code;
Разрешения - это коллекция, сопоставленная с классом пользователя.
Ответ 5
Я думаю, что вы хотите получить соединение. Это объединение, которое возвращает столбцы из базы данных, которые превращаются в объекты, но где эти объекты добавляются только в кеш сеанса, а не возвращаются в результаты.
Существуют различные способы сделать это через JPA, устаревший API Hibernate, API устаревших критериев и т.д.
Если вы используете собственный SQL, вы можете сделать это, вызвав SQLQuery::addFetch
, заменив ваш вызов на addJoin
с:
qry.addFetch("entity2", "entity1", "fk");
Или что-то в этом роде. Должен признаться, я не совсем понимаю, что должны означать параметры, и я не мог найти хорошую документацию на нем с некоторыми быстрыми поисками.