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

时间:2011-09-21 21:13:47

标签: java hibernate inner-join

我似乎对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 objectWarehouse object的对象。

这是预期的。问题是hibernate将产品的id和名称分配给仓库对象id和name属性。就创建Warehouse项目而言,好像连接结果中的前两列都过度了。 Product对象始终包含正确的数据。

有关找到解决此问题的方法的任何建议,因此非常感谢表示正确仓库数据的ID和名称列。

提前致谢。

3 个答案:

答案 0 :(得分:9)

使用{}表单可以避免列名重复出现问题:

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”等不等于列   在映射中指定(“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.*}符号是“所有属性”的简写。

答案 1 :(得分:6)

Reference

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

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

答案 2 :(得分:6)

正如coding_idiot所说,也许您不知道查询结果的实体,因为它们来自不同的类,您可以访问元素中的每个对象。

  1. 创建List<Object>以检索查询结果(示例: List<Object> objs = (List<Object>)query.getResultList();
  2. 使用for(示例:for (Object obj : objs){...}
  3. 遍历此数组
  4. List<Object>的每个元素都有Object[] 将每个元素强制转换为此类(例如:Object[] o = (Object[]) obj;
  5. 通过索引号访问元素(示例: o[4]
  6. 代码示例:

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