2011-05-13 82 views
10

我正在使用JPQL,並希望在構造函數表達式中接收一些常規參數和集合以直接創建DTO對象。但是,如果集合是空的,我總是得到一個錯誤,因爲他不找到合適的構造函數:JPQL:在構造函數表達式中接收集合

的DTO級看起來如下:

public class DTO { 
    private long id; 
    private String name; 
    private Collection<Child> children; 

    public DTO (long id, String name, Collection<Child> children){ 
    this.id = id; 
    this.name = name; 
    this.children= children; 
    } 
} 

的兒童類:

public class Child { 
    private String name; 
    private int age; 
} 

現在構造函數表達式看起來如下:

return (List<DTO>) getEm().createQuery("SELECT DISTINCT NEW de.DTO(p.id, p.name, p.childs) 
              FROM Parent p").getResultList(); 

當前的問題是,t如果Collection p.childs爲空,它表示它沒有找到正確的構造函數,它需要(long,String,Child)而不是(long,String,Collection)。

你有任何一種解決方案,或者它是根本無法在構造器表達式中使用集合?

哦,還有一件事:如果我輕鬆創建兩個構造函數(...,集合孩子和...,孩子孩子)我沒有結果,但沒有錯誤...在我的眼睛裏並不真正meetiyng: -/

+0

我想你已經忘記發佈你的'Parent'類了。此外,「孩子」的複數形式是「孩子」。 – Behrang 2011-05-14 11:37:08

+0

您是否嘗試添加條件來查詢 - 「WHERE p.childs不是空和尺寸(p.childs)<> 0」 – 2011-05-14 12:15:43

回答

8

這不是一個答案。

就我所見,JPA 2.0規範並沒有允許在構造函數表達式中使用集合作爲參數。第4.8節定義了一個構造函數表達式這樣的:

constructor_expression ::= 
     NEW constructor_name (constructor_item {, constructor_item}*) 
constructor_item ::= 
     single_valued_path_expression | 
     scalar_expression | 
     aggregate_expression | 
     identification_variable 

single_valued_path_expression是這聽起來像 - 指向某種(如p.id)的標量屬性表達式,一個scalar_expression也指向的表達式標量,aggregate_expression是像sum這樣的函數的應用程序,它將多值表達式簡化爲一個標量,而identification_variable是對您正在查詢的類型的引用。其中沒有一個可以收藏價值。假設我已經閱讀了正確的規格。因此,如果您的JPA提供程序允許您在構造函數表達式中使用集合值參數,那是因爲它超出了規範。這是非常好的,但不是你可以依賴的東西!

+0

嘿湯姆安德森, 非常感謝您提供此信息。我只是使用Eclipse鏈接,所以我猜測,不使用Hibernate或其他的東西,它也作用於更高層,我不會成功與此。 @評論:是的,我忘了父母課程,但我也只有一個ID,一個名字和一個集合有或沒有孩子。所以像IS NOT EMPTY這樣的條件不符合我的目標,我也需要沒有孩子的父母。感謝您的幫助。 – Florian 2011-05-14 19:08:25

+0

與JPA 2.1中的相同,請參見章節4.14 BNF,第211頁。 – 2017-07-03 07:11:50

3

嘗試,

public DTO (long id, String name, Object children) 
1

我有一個類似的問題,在DTO構造試圖「對象」詹姆斯建議,但子對象被通過,它似乎是唯一的第一個孩子,而不是預期列表/兒童數組。

我結束了一個「正常」查詢,在for循環中創建所有的DTO。

TypedQuery<Parent> query = em.createQuery("SELECT p FROM Parent p", Parent class); 
     List<Parent> list = query.getResultList(); 
     List<DTO> result = new ArrayList<>(); 
     for (Parent p : list) 
     { 
      DTO dto = new DTO(); 
      //set dto props and fill collection 
      result.add(obj); 
     } 
     return result;