2011-05-23 55 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