2011-12-08 21 views
1

我有一個要求使用來自HQL的報表友好的查詢。也就是說,每列由標準的Java類型(Long,Integer,String,List)表示,而不是映射類。這些值將被第三方庫使用,所以我對後處理的控制非常有限。將集合展平爲HQL查詢的一部分?

我的例子中的物體樹是這個樣子:

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對象。

我已經嘗試以下操作:

  • 列表中的子查詢中使用了「新」的關鍵字。即「從a選擇a.x,(選擇新列表(a.y.z.v))」。如果有必要,我可以將列表的內容轉換爲csv,但這會導致語法錯誤。

  • 在子查詢中對自定義對象使用「new」關鍵字。即「從一個」選擇a.x,(選擇新的custom.package.ListToCsvObject(a.y.z))。這導致與第一次嘗試相同的錯誤

  • 在select中使用「elements()」關鍵字。不幸的是,這個關鍵字似乎只能在「in」,「exists」子句(等)內工作,而不是實際返回的值。

,我們已經能夠找到的唯一的解決辦法是在數據庫中創建一個存儲過程和使用,但這樣的解決方案是通過HQL痛苦的緩慢(它變成一分一秒查詢到30第二個查詢),因此我們不想繼續這樣做。

能夠做出Hibernate映射一些有限的變化(這樣我就可以添加@formula等),但我寧願不要有使數據庫架構發生重大變化,以支持它。 (所以不,我不想在數據庫中創建一個非規範化的「csv_value」列!)

任何人都可以推薦一些代碼,否則,解決這個問題的替代方法?

回答

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等)。

+0

這不會從數據庫返回整個'y'對象數組,而不僅僅是y.z.v數組嗎?在這種情況下,z是一個非常大的對象,我不想爲速度原因檢索,我只想要'v'值。 (我同意這是Hibernate的一個糟糕的用法。如果我有選擇,我會在這種情況下使用直接JDBC,但不幸的是它是我給出的約束之一。) – Erica

+0

也許你可以嘗試「從」中選擇新的ResultVO(a.x,a.y.z.v)。你是否有從z到y和y的反向引用 - 如果在那裏你可能能夠進行連接來獲得a.x和z.v. – gkamal