【问题标题】:Flatten a collection as part of an HQL query?将集合展平为 HQL 查询的一部分?
【发布时间】:2012-01-15 14:50:38
【问题描述】:

我需要使用来自 HQL 的报告友好型查询。也就是说,每一列都由标准 Java 类型(Long、Integer、String、List)而不是映射类表示。这些值将被第三方库使用,因此我对后处理的控制非常有限。

我的示例对象树如下所示:

a.x
a.y (a collection of z)
a.y.z[0].v
a.y.z[1].v
a.y.z[2].v

我想查询以检索两列。第一列是普通的“a.x”字段,第二列是所有 a.y.z.v 值的逗号分隔列表的字符串。如果这是不可能的,那么让第二列作为 a.y.z.v 值的 Java 列表返回将是令人满意的。

简而言之,我想将 a.y.z.v 集合展平为 csv 字符串或查询内部的 List 对象。

我已经尝试了以下方法:

  • 在列表子选择中使用“new”关键字。即,“选择 a.x,(从 a 中选择新列表(a.y.z.v))”。如有必要,我可以将列表的内容转换为 csv,但这会导致语法错误。

  • 在子选择中对自定义对象使用“new”关键字。即,“选择 a.x, (select new custom.package.ListToCsvObject(a.y.z)) from a”。这导致与第一次尝试相同的错误

  • 在选择中使用“elements()”关键字。不幸的是,这个关键字似乎只在“in”、“exists”子句(等)中起作用,而不是实际的返回值。

我们能够找到的唯一解决方案是在数据库中创建一个存储过程并使用它,但这样的解决方案通过 HQL 非常缓慢(它将亚秒查询变成 30 秒查询)并且因此,我们不想继续这样做。

能够对 Hibernate 映射进行一些有限的更改(因此我可以添加 @formula 等),但我希望不必对数据库架构进行重大更改以支持它. (所以不,我不想在数据库中创建一个非规范化的“csv_value”列!)

任何人都可以建议一些代码,或者,如果失败了,可以提供解决此问题的替代方法吗?

【问题讨论】:

    标签: java hibernate hql


    【解决方案1】:

    尝试这样的方法应该可以。将列表展平为逗号分隔的字符串是在 VO 类的构造函数中完成的。你也可以看看resultTransformer,你可以创建一个自定义的resultTransformer并将它附加到查询中。

    class ResultVO {
    
    String x;
    String y;
      public ResultVO(String x,List<Z> y) {
         this.x = x;
         this.y = createCSV(y);
      }
    }
    
    then in HQL
    select new ResultVO(a.x,a.y) from a
    

    警告 - 这不是使用 JPA 的好方法。如果您的大多数用例都是这样,您应该认真重新考虑使用其他一些持久性方法(ibastis、spring jdbc 模板 + sql 等)。

    【讨论】:

    • 这不是从 db 返回整个 'y' 对象数组,而不仅仅是 y.z.v 的数组吗?在这种情况下,z 是一个非常大的对象,出于速度原因我不想检索它,我只想要“v”值。 (我同意这是对 Hibernate 的不良使用。如果可以选择,我会在这种情况下使用直接 JDBC,但不幸的是,这是我受到的限制之一。)
    • 也许您可以尝试“从 a 中选择新的 ResultVO(a.x,a.y.z.v)”。您是否有从 z 到 y 和 y 到 a 的反向引用 - 如果有,您可能可以进行连接以获取 a.x 和 z.v。
    • 在我最初的研究中,我 +1 了这个答案,因为它证实了我希望做的事情是可能的,但也如(JPQL:在构造函数表达式中接收集合)[@ 987654322@,这似乎不可能开箱即用。当您在 JPQL 中使用 a.y 类型的语法时,您会收到关于需要在 c'tor 中收集集合的错误,如果您修复了该错误,现在 sql 语法会变得混乱(只有“.”作为列表达式)。请参阅我在另一个问题中的评论:link
    猜你喜欢
    • 2010-09-09
    • 2013-11-29
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    相关资源
    最近更新 更多