【问题标题】:Hibernate Native SQL Query retrieving entities and collectionsHibernate Native SQL 查询检索实体和集合
【发布时间】:2011-08-25 07:51:08
【问题描述】:

这是我的情况,我有两个基本的 POJO,我给出了一个简单的休眠映射:

Person
  - PersonId
  - Name
  - Books

Book
  - Code
  - Description

My SQL 查询返回如下所示的行:

PERSONID NAME       CODE DESCRIPTION
-------- ---------- ---- -----------
1        BEN        1234 BOOK 1
1        BEN        5678 BOOK 2
2        JOHN       9012 BOOK 3

我的休眠查询如下所示:

session.createSQLQuery("select personid, name, code, description from person_books")  
       .addEntity("person", Person.class)
       .addJoin("book", "person.books")
       .list();

这是每个部分:休眠文档的第 18.1.3 节: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/querysql.html#d0e17464

我希望在我的列表中得到 2 个 Person 对象,其中包含书籍集合中的书籍对象:

List
 |- Ben
 |   |- Book 1
 |   '- Book 2
 '- John
     '- Book 3

我实际看到的是:

List
 |- Object[]
 |   |- Ben
 |   |   |- Book 1
 |   |   '- Book 2
 |   '- Book 1
 |- Object[]
 |   |- Ben
 |   |   |- Book 1
 |   |   '- Book 2
 |   '- Book 2
 '- Object[]
     |- John
     |   '- Book 3
     '- Book 3

有谁知道使用这种方法是否可以得到我想要的东西?

【问题讨论】:

    标签: java hibernate native-sql


    【解决方案1】:

    扩展马修斯的答案。 要强制休眠只返回人员列表,请执行以下操作:

    List<Person> peopleWithBooks = session.createSQLQuery(
       "select {p.*}, {b.*} from person p, book b where <complicated join>").
         .addEntity("p", Person.class)
         .addJoin("b", "p.books")
         .addEntity("p", Person.class)
         .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
         .list();
    

    无需额外调用 db 即可获取和初始化关联的 Book 实体。

    重复的

     .addEntity("p", Person.class)
    

    是必要的,因为

     .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    

    对添加的最后一个实体进行操作。

    【讨论】:

    • 这将获取 Person 和 Book 的所有内容。如果您只想选择某些属性来提高性能怎么办。据我了解,除了 * 或 p.* 之外的任何内容都不起作用。
    • 使用{p.*}, {b.*} 还修复了books 的额外子选择问题。
    • 不管与一个人相关的书籍数量,这是否只获取每人一本书?我有一个类似的问题并使用了这个解决方案。它为“加入”实体返回一个集合,但不返回其中的所有值。设置大小为 1。
    • 重复.addEntity 的解决方法帮助了我。我在用另一个提案发出类似的问题后发现了这个问题 - stackoverflow.com/q/62554257/653539
    【解决方案2】:

    以下对我有用:

    session.createSQLQuery("select p.*, b.* from person p, book b where <complicated join>").
    .addEntity("person", Person.class).addJoin("book", "person.books").list();
    

    这将返回一个Object[],其中包含一个Person 列表,每个列表都包含一个Books 列表。它在单个 SQL 选择中执行此操作。我认为您的问题是您没有专门将 person 别名为任何东西。

    编辑:该方法返回一个 Object[],但该数组填充了 Person 实例,并且只有 Person 实例。

    如果 Hibernate 不了解如何映射到您的类,或者如果它不了解如何映射连接,它将返回一个对象列表。确保每行只有一个 Person/Book 组合。

    【讨论】:

    • 当他们拥有不止一本书时,我所期待的是一个 Person 列表,而不是一个包含重复人员的 Object[] 列表。请参阅我的答案以获取指向休眠 jira 错误报告的链接。
    • 抱歉,为了清楚起见,该方法返回一个 Object[],但数组中填充了 Person,并且只有 Person。我那里没有书。
    【解决方案3】:

    HHH-2831 Native SQL queries with addJoin or return object arrays instead of single Entities

    此行为是由已知错误引起的。哎呀,应该更努力地搜索!

    【讨论】:

    【解决方案4】:

    您的查询应该在 person 表上而不是 person_books 上吗?

    session.createSQLQuery("select * from person")  
       .addEntity("person", Person.class)
       .addJoin("book", "person.books")
       .list();
    

    【讨论】:

    • 为了简洁起见,我已经简化了这个例子。在我的实际使用中,“person_books”是一个复杂的查询,如果没有我在查询中提供它,hibernate 无法获取“book”的信息。我正在为 Person 检索大量行,并且希望不必执行额外的查询来查找每个 Person 的 Books。如果我找不到解决方案,我可能会使用这种方法,但只是跳过 Person 不变的行。
    【解决方案5】:

    AFAIK,不可能从 SQL 查询中获取“合并”实体。你只会得到一个对象数组。在这种情况下,我为合并实体创建了一个新的构造函数,该构造函数将对象数组作为参数。然后我手动构建。

    【讨论】:

      猜你喜欢
      • 2020-12-04
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      相关资源
      最近更新 更多