2011-08-09 43 views
8

我有一個Hibernate標準調用,我想在一個SQL語句中執行。我想要做的是選擇具有一系列值的屬性的子項(SQL IN子句)的父實例,同時使用外連接加載子項。這是我到目前爲止有:有限孩子的休眠標準

Criteria c = session.createCriteria(Parent.class); 

c.createAlias("children", "c", CriteriaSpecification.LEFT_JOIN) 
      .setFetchMode("c", FetchMode.JOIN) 
      .add(Restrictions.in("c.property", properties)); 

c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

return c.list(); 

下面是一些樣本數據:

Parent 
Parent ID 
A 
B 
C 

Children 
Child ID Parent ID property 
...   A   0 
...   A   2 
...   A   7 
...   B   1 
...   C   1 
...   C   2 
...   C   3 

我想要做的就是回到父母和他們的孩子,如果一個孩子有平等的財產我綁定參數。假設屬性是包含{2}的數組。在這種情況下,該調用將返回父母A和C,但他們的子集合將只包含元素2。父[兒童]:

A [2] & C [2]

我想是:

A [0,2,7] & C [1,2 3]

如果這不是一個bug,它似乎是一個破碎的語義。我沒有看到如何調用A.getChildren()或C.getChildren()並返回1條記錄會被認爲是正確的 - 這不是一個投影。即如果我增加了查詢使用默認選擇獲取,它返回正確的孩子集合,albiet與查詢的衆多:

c.createAlias("children", "c").add(
     Restrictions.in("c.property", properties)); 

這是一個錯誤?如果不是,我怎麼能達到我想要的結果?

回答

1

的getChildren()是的getter/setter的只是名字,你的查詢將確定對象是如何被填充。

我要在這裏猜測,第一部分吐出

SELECT * FROM Parent 
INNER JOIN Child c ON ... 
WHERE c.property in (x,y,z) 

它沒有得到你想要的東西。你許了什麼會想,如果你是在原始SQL寫這做的是:

SELECT * FROM Parent 
WHERE ParentID IN (SELECT DISTINCT parentID FROM Child WHERE c.property in (x,y,z)) 

適當地重新安排你的標準可能會做的伎倆,如果最後一個不生產這種查詢。 (難道你還張貼的內容Hibernate是產生每個?)

+1

對,SQL是簡單的部分。我正在尋找的是標準調用。 ;)另外,請記住,這將需要外部聯接來填充子實體。 –

+0

第二個查詢是否獲得了父項並且延遲加載子項? – dfb

+0

是的,對於每個返回的父記錄,正在執行的子查詢正是我試圖避免的。看起來這可能實際上是一個缺陷,但我很好奇,如果任何人有解決方法:https://hibernate.onjira.com/browse/HHH-3524 –

0

我將開始與兒童類標準。你會得到所有孩子的列表,然後你可以迭代並獲得每個孩子的父母。

2
 Criteria c = session.createCriteria(Parent.class); 

    c.createAlias("children", "children"); 
    c.add(Restrictions.in("children.property", properties)); 

    c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

    return c.list(); 
0

這可以在工作中完成。

Criteria c1 = session.createCriteria(Child.class); 
c1.add(Restrictions.in("property", properties)); 
c1.setProjection(Projections.distinct(Projections.property("parentId"))); 
List<Integer> parentIds = c1.list(); 

Criteria c2 = session.createCriteria(Parent.class); 
c2.createAlias("children", "children"); 
c2.add(Restrictions.in("id", parentIds)); 
return c2.list();