Возвращение нескольких типов объектов с помощью hibernate с использованием внутреннего соединения
Кажется, у меня проблемы с запросом в спящем режиме. Я выполняю внутреннее соединение на двух таблицах.
SELECT * FROM product p INNER JOIN warehouse w ON p.wid = w.id
Таблица продуктов:
id | name | wid | price | stock .....
Таблица складов:
id | name | city | lat | long .....
Результат соединения:
id | name | wid | price | stock | id | name | city | lat | long .....
Когда я запускаю запрос.
Session.createSQLQuery(this.query)
.addEntity("p", Product.class)
.addEntity("w", Warehouse.class).list();
Итак, для каждого результата я получаю объект, содержащий Product object
и Warehouse object
.
Ожидается. Проблема заключается в том, что hibernate присваивает идентификатор и имя продукта свойствам id и имени объекта хранилища. Как будто первые два столбца в результате соединения заканчиваются, когда дело доходит до создания проекта Warehouse. Объект Product всегда содержит правильные данные.
Любые предложения по поиску пути вокруг этой проблемы, так что столбцы идентификаторов и имен, представляющие правильные данные Warehouse, будут очень оценены.
Спасибо заранее.
Ответы
Ответ 1
Используйте форму {}, чтобы избежать проблем с дублированием имени столбца:
SELECT {p.*}, {w.*} FROM product p INNER JOIN warehouse w ON p.wid = w.id
Из Hibernate Reference Documentation, раздел 18.1.4. Возврат нескольких объектов:
До сих пор имена столбцов набора результатов считаются такими же, как имена столбцов, указанные в документе сопоставления. Это может быть проблематичный для SQL-запросов, которые объединяют несколько таблиц, поскольку тот же имена столбцов могут отображаться более чем в одной таблице.
В следующем запросе (например, скорее всего, не удастся):
sess.createSQLQuery("SELECT c.*, m.* FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class)
Запрос был предназначен для возврата двух экземпляров Cat для каждой строки: кошка и его мать. Запрос будет, однако, терпеть неудачу, потому что есть конфликт имен; экземпляры сопоставляются с теми же именами столбцов. Кроме того, на в некоторых базах данных возвращенные псевдонимы столбцов, скорее всего, будут формы "c.ID", "c.NAME" и т.д., которые не равны столбцам указанных в сопоставлениях ( "ИД" и "ИМЯ" ).
Следующая форма не уязвима для дублирования имени столбца:
sess.createSQLQuery("SELECT {cat.*}, {mother.*} FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
.addEntity("cat", Cat.class)
.addEntity("mother", Cat.class)
Указанный запрос:
строка запроса SQL, с заполнителями для Hibernate для ввода столбца псевдонимы объектов, возвращаемых запросом. {cat.*}
и Используемая выше обозначение {mother.*}
является сокращением для "всех свойств".
Ответ 2
Как сказал coding_idiot, возможно, вы не знаете объект для результата запроса, потому что они из разных классов, вы можете получить доступ к каждому объекту в элементе.
- Создайте
List<Object>
для получения результата запроса (пример:
List<Object> objs = (List<Object>)query.getResultList();
)
- Итерируйте через этот массив, используя for (Пример:
for (Object obj : objs){...}
)
- Каждый элемент
List<Object>
имеет Object[]
, поэтому
отбросить каждый элемент этого класса (Пример: Object[] o = (Object[]) obj;
)
- Доступ к элементу через его индексный номер (Пример:
o[4]
)
Пример кода:
Query query = JPA.em().createNativeQuery("SELECT * FROM product p
INNER JOIN warehouse w ON p.wid = w.id");
/* I suppose that it return fields sorted by entities and field in
database:
*
* 0: product.id | 1: product.name | 2: product.wid | 3: product.price | 4: product.stock | n-1: product.N-1Field
* n: warehouse.id | n+1: name | n+2: warehouse.city | n+3: warehouse.lat | n+4: warehouse.long | m-1: warehouse.M-1Field
*
* Join result: id | name | wid | price | stock | ... | id | name | city | lat | long | ...
*/
List<Object> objs = (List<Object>)query.getResultList();
for (Object obj : objs) {
Object[] o = (Object[]) obj;
String productId = String.valueOf(o[0]);
String productName = String.valueOf(o[1]);
String productWid = String.valueOf(o[2]);
... }
Ответ 3
Ссылка
Если объекты не принадлежат к одному классу, то здесь образец:
public static void main(String[] args) {
Session sess = NewHibernateUtil.getSessionFactory().openSession();
SQLQuery q = null;
String query = "select a.*, u.* from user u, account a where a.iduser=u.iduser";
q = sess.createSQLQuery(query);
q.addEntity(User.class);
q.addEntity(Account.class);
List lst = q.list();
System.out.println("" + lst.size());
for (int i = 0; i < lst.size(); i++) {
System.out.println(((Object[]) lst.get(i))[0]); //account bean, actually this is in reverse order - so this is user bean
System.out.println(((Object[]) lst.get(i))[1]); //user bean & this account bean
}
sess.close();
}