将集合展平为HQL查询的一部分?

时间:2011-12-08 05:05:31

标签: java hibernate hql

我需要使用来自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 String或查询内部的List对象。

我已尝试过以下内容:

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

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

  • 在select中使用“elements()”关键字。不幸的是,这个关键字似乎只能在“in”,“exists”子句(etc)中使用,而不是实际的返回值。

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

能够对Hibernate映射进行一些有限的更改(所以我可以添加@formula等)但我宁愿不必对数据库模式进行重大更改来支持它。 (所以不,我不想在数据库中创建非规范化的“csv_value”列!)

有人可以建议一些代码,或者,如果没有这样,可以采用另一种方法来解决这个问题吗?

1 个答案:

答案 0 :(得分: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 template + sql等)。