2011-05-23 74 views
4

我有這樣的實體:Hibernate的標準API - 過濾集合屬性

@Entity 
public class Album { 

    private Integer id; 
    private Integer ownerId; 
    private String name; 
    private String description; 
    private Date created; 
    @OneToMany @JoinColumn(name = "albumId") 
    private Set<AlbumUser> users = new HashSet<AlbumUser>(); 
    @OneToMany @JoinColumn(name = "albumId") 
    private Set<Picture> pictures = new HashSet<Picture>(); 
} 

和另一個問題:

@Entity 
public class Picture { 

    private Integer id; 
    private Integer creatorId; 
    private Integer albumId; 
    private Date created; 
    private String title; 
    private String description; 
    @ManyToOne @JoinColumn(name = "eventId") 
    private Event event; 
} 

使用標準的API我想用過濾集Picturs的獨特AlbumDs。我嘗試這樣的:

public Album read(Integer albumId, Set<Integer> picFilter) { 
     Criteria crit = getCurrentSession().createCriteria(Album.class, "album"); 
     crit.add(Restrictions.idEq(albumId)); 
     if (picFilter != null && !picFilter.isEmpty()) { 
      crit = crit.createAlias("album.pictures", "picture"); 
      crit.add(Restrictions.in("picture.event.id", picFilter)); 
      crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
     }  
     Album resultDs = (Album) crit.uniqueResult();  
     return resultDs; 
} 

在這裏我得到相冊與所有圖片關聯。他們根本沒有被過濾。 當我嘗試執行由記錄器打印的查詢時,我只得到四行,這是給定eventId的圖片數量,但在相冊中我獲取了所有圖片。

我也嘗試過其他ResultTransformers,但最終得到了很多結果(4)沒有明確的結果。

我該錯過什麼或做錯了什麼?

+0

原諒我的斷語;) – 2011-05-23 19:46:47

+0

做您嘗試觀看查詢休眠產生什麼SQL ? – 2011-05-23 21:05:14

+0

我已經寫過了。有一個SQL查詢只能檢索4張圖片,但我後來發現,還有另一個檢索所有這些圖片。我開始相信我的案例不適用於Criteria API :( – 2011-05-23 21:34:03

回答

5

,無法篩選的通過在查詢上的集合限制與實體相關類別的內容。該查詢只會獲取相冊。集合的內容可以在訪問集合時稍後獲取。您只需過濾相冊即可僅檢索包含帶有事件ID的圖片的相冊。

如果集合只包含符合條件的圖片,並且您將獲得部分集合,則會導致更新出現問題,因爲Hibernate會認爲已過濾的項目已被刪除,並會更新數據庫以反映該更改,實際上從集合中刪除項目。

如果您只想接收集合中的部分項目,則可以使用Session.createFilter()方法。唯一的問題是,它目前只支持HQL查詢。

+0

是的,你可以使用subcriteria,如下所述。但它有點令人費解,我更喜歡使用HQL和JOIN。 – 2014-05-08 13:30:28

1

我記得這是我最近做的一件事。您是否嘗試過這樣的:

if (picFilter != null && !picFilter.isEmpty()) { 
    Criteria subCriteria = crit.createCriteria("album.pictures"); // Or just 'pictures?' 
    Disjunction or = Restrictions.disjunction(); 

    for (Integer id : picFilter) 
     or.add(Restrictions.idEq(id)); 
    subCriteria.add(or); 
    crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
} 
+0

你能幫我用http:// stackoverflow。com/questions/7687409/hibernate-criteria-query-for-collection-table/7693793#7693793我在那裏附加了一個賞金..非常需要幫助 – 2011-10-10 06:18:50

0

試試這個:

Criteria crit = getCurrentSession().createCriteria(Album.class, "album"); 
    crit.add(Restrictions.idEq(albumId)); 
    if (picFilter != null && !picFilter.isEmpty()) { 
     crit.createAlias("album.pictures", "picture"); 
     crit.createAlias("picture.event", "event"); 
     crit.add(Restrictions.in("event.id", picFilter)); 
     crit.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 
    }  
0

如果使用別名與left_join,它將返回滿足相關條件只是子對象。否則它返回滿足條件但是與所有子對象集一致的主對象。

crit = crit.createAlias("album.pictures", "picture", CriteriaSpecification.LEFT_JOIN); 

此方法deprrecated在一些休眠的版本,如果是的話,你可以用下面的解決方案,這也: criteria with filtered complex set