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");

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