Возвращение нескольких типов объектов с помощью 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();
    }