2015-10-21 55 views
1

我有一個查詢我想在一張桌子上運行,我們將其稱爲parent,其中我抓取符合特定條件的所有行。在SQL:如何使用Hibernate加載實體列表以及這些實體相關實體的子集?

select * from parent where status = 'COMPLETE'; 

我有這個表,並定義爲Hibernate的實體另一個相關的表(child),使得:

@Entity 
@Table(name = "parent") 
public class Parent { 
    //... 
    @OneToMany(mappedBy = "parent") 
    private Set<Child> children; 
    //... 
} 

@Entity 
@Table(name = "child") 
public class Child { 
    //... 
    @ManyToOne 
    @JoinColumn(name = "parent_id") 
    private Parent parent; 

    @Column(name = "key") 
    private String key; 
    //... 
} 

我想我的查詢也拉兩個可選的子記錄,其中key是兩個值之一。所以,在SQL:

select * 
from parent p, child ca, child cb 
where p.status = 'COMPLETED' 
and p.id *= ca.parent_id 
and ca.key = 'FIRST_KEY' 
and p.id *= cb.parent_id 
and cb.key = 'SECOND_KEY'; 

我能做到這一點在Hibernate中從第一次查詢就可以抓取的結果,並遍歷children集合尋找我想要的行,但是這是非常低效的:一個查詢做兩個外加入一個查詢+每個查找我關心的孩子的附加查詢。

有沒有一種方法可以在Hibernate中的上述查詢中複製外部連接,其中返回的對象只有children集合只填充了我感興趣的兩個(或更少,因爲它們是可選的)實體?

回答

1

您不需要兩個外部連接。你可以簡單地使用這個HQL和Hibernate將正確的孩子添加到正確的父母:

List<Parent> parentList = session 
     .createQuery("from Parent p left join fetch p.children c" + 
        " where p.status = 'COMPLETE' " + 
        " and (c.key = 'FIRST_KEY' or c.key = 'SECOND_KEY')") 
     .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 
     .list(); 

for(Parent parent:parentList) { 
    System.out.println(parent);; 
} 

希望解決您的問題。

+0

感謝您的幫助。我接受這個解決方案,但經過大量研究後,結果證明我需要的是能夠在連接上指定一個「on」子句來限制外部連接表。 Hibernate用'with'子句支持這個,但這對我也不適用。獲取一個'antlr.SemanticException:with-clause不允許獲取關聯;使用過濾器'。如果您確定這些值將出現在外部聯接表中,那麼您的解決方案將起作用。如果記錄可能不存在,查詢將不會檢索您所期望的記錄。 –