繁体   English   中英

Hibernate 标准 API - 过滤集合属性

[英]Hibernate Criteria API - Filtering collection property

我有这样的实体:

@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 我想获得带有过滤图片集的唯一 AlbumD。 我尝试这样的事情:

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),结果并不明显。

我错过了什么或做错了什么?

您无法通过在查询中包含对集合的限制来过滤与实体关联的 Collections 的内容。 该查询将仅获取专辑。 可以在以后访问 Collection 时获取 Collection 的内容。 您所做的只是过滤相册以仅检索那些包含带有事件 ID 的图片的相册。

如果集合仅包含与您的条件匹配的图片并且您将获得部分集合,则会导致更新问题,因为 Hibernate 然后认为过滤的项目已被删除,并会更新数据库以反映该更改,实际上删除了这些项目从收藏。

如果您只想从集合中接收一些项目,您可以使用Session.createFilter()方法。 唯一的问题是,它目前只支持 HQL 查询。

我记得这是我最近做的事情的一个问题。 你有没有试过这个:

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); 
 }

如果将别名与 left_join 一起使用,它将仅返回满足相关条件的子 object。 否则,它返回满足条件但设置了所有子 object 的主 object。

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

此方法在某些 hibernate 版本中已弃用,如果是这样,您也可以使用以下解决方案: 过滤复杂集的标准

尝试这个:

    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);   
    }     

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM