使用内部联接使用休眠返回多个对象类型

2022-09-02 13:07:24

我似乎在休眠状态下查询时遇到了一些困难。我正在对两个表执行内部联接。

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

因此,对于每个结果,我都会得到一个包含 a 和 a 的对象。Product objectWarehouse object

这是预料之中的。问题是休眠将产品的 ID 和名称分配给仓库对象 ID 和 name 属性。就好像在创建 Warehouse 项目时,联接结果中的前两列就被覆盖了一样。产品对象始终包含正确的数据。

任何关于找到解决此问题的方法的建议,以便ID和名称列表示正确的仓库数据将不胜感激。

提前致谢。


答案 1

使用 {} 形式可避免列名重复的问题:

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

摘自《休眠参考文档》第 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”等形式,它们不等于映射中指定的列(“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.*}


答案 2

参考

如果实体不是来自同一类,那么下面是一个示例:

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

推荐