Возврат нескольких типов объектов с использованием Hibernate с использованием внутреннего соединения - PullRequest
17 голосов
/ 22 сентября 2011

Кажется, у меня возникли трудности с запросом в спящем режиме.Я выполняю внутреннее соединение двух таблиц.

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 назначает идентификатор и имя продукта для свойства идентификатора и имени объектов хранилища.Похоже, что первые два столбца в результате объединения перестают работать, когда дело доходит до создания проекта хранилища.Объект Product всегда содержит правильные данные.

Любые предложения по поиску пути решения этой проблемы, поэтому столбцы идентификаторов и имен, представляющие правильные данные хранилища, будут высоко оценены.

Заранее спасибо.

Ответы [ 3 ]

9 голосов
/ 22 сентября 2011

Используйте форму {}, чтобы избежать проблем с дублированием имени столбца:

SELECT {p.*}, {w.*} FROM product p INNER JOIN warehouse w ON p.wid = w.id

С Справочная документация Hibernate , раздел 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 в строке: cat и его мать. Однако запрос не будет выполнен из-за конфликта имен; экземпляры сопоставляются с одинаковыми именами столбцов. Кроме того, на в некоторых базах данных возвращенные псевдонимы столбцов, скорее всего, будут формы "c.ID", "c.NAME" и т. д., которые не равны столбцам указано в сопоставлениях («ID» и «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.*} обозначение, использованное выше, является сокращением для "всех свойств".

6 голосов
/ 30 июня 2015

Как сказал coding_idiot, возможно, вы не знаете сущность для вашего результата запроса, поскольку они принадлежат разным классам, вы можете получить доступ ко всем объектам в элементе.

  1. Создать List<Object> для получения результата запроса (Пример: List<Object> objs = (List<Object>)query.getResultList();)
  2. Итерация по этому массиву с использованием for (Пример: for (Object obj : objs){...})
  3. Каждый элемент List<Object> имеет Object[], поэтому приведение каждого элемента к этому классу (Пример: Object[] o = (Object[]) obj;)
  4. Доступ к элементу через его индекс (например: 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]);

        ... }
6 голосов
/ 26 ноября 2013

Ссылка

В случае, если сущности не принадлежат к одному классу, вот пример:

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();
    }
...