java Hibernate Criteria API - 过滤集合属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6102152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate Criteria API - Filtering collection property
提问by Patryk Dobrowolski
I have such entity:
我有这样的实体:
@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>();
}
and another one:
还有一个:
@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;
}
Using Criteria API I want to get unique AlbumDs with filtered set of Picturs. I try something like this:
使用 Criteria 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;
}
And here I get Album with all pictures associated. They're not filtered at all. When I try to execute query printed by a logger, I get only four rows wich is the number of pictures with given eventId, but in the Album I get all pictures.
在这里,我得到了包含所有图片的相册。它们根本没有过滤。当我尝试执行由记录器打印的查询时,我只得到四行,即具有给定 eventId 的图片数量,但在相册中我得到了所有图片。
I also tried other ResultTransformers, but eventualy got many result (4) not distinct one.
我还尝试了其他 ResultTransformers,但最终得到了许多结果 (4),而不是不同的结果。
What do I miss or do wrong?
我错过了什么或做错了什么?
回答by Reboot
You can not filter the content of Collections associated with an entity by including Restrictions on the Collection in the query. The query will only fetch the Albums. The content of the Collection can be fetched later, when the Collection is accessed. All you do is filter the Albums to retrieve only those Albums that contain the Pictures with the event ids.
您不能通过在查询中包含对集合的限制来过滤与实体关联的集合的内容。查询只会获取相册。当访问集合时,可以稍后获取集合的内容。您所做的就是过滤相册以仅检索那些包含带有事件 ID 的图片的相册。
If the Collection would only contain the Pictures that match your Criteria and you would get a partial Collection it would cause problems on updates, because Hibernate then think the filtered items have been removed and would update the database to reflect that change, actually removing the items from the Collection.
如果集合只包含与您的标准匹配的图片并且您将获得部分集合,则会导致更新出现问题,因为 Hibernate 然后认为过滤的项目已被删除,并会更新数据库以反映该更改,实际上是删除项目从集合。
If you want to receive only some items from a Collection you can use the Session.createFilter()method. The only problem is, that it only supports HQL queries currently.
如果您只想从集合中接收一些项目,您可以使用Session.createFilter()方法。唯一的问题是,它目前只支持 HQL 查询。
回答by jbrookover
I recall this being an issue for something I did recently. Have you tried this:
我记得这是我最近做的事情的一个问题。你有没有试过这个:
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);
}
回答by sul
try this:
试试这个:
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);
}
回答by Mustafa Kemal
If you use alias with left_join, it will return just sub object which satisfy related condition. Otherwise it returns main object which satisfy conditions but with all of sub object set.
如果将别名与 left_join 一起使用,它将只返回满足相关条件的子对象。否则,它返回满足条件但设置了所有子对象的主对象。
crit = crit.createAlias("album.pictures", "picture", CriteriaSpecification.LEFT_JOIN);
This method is deprrecated in some hibernate version, if so you can use below solution for it too: criteria with filtered complex set
此方法在某些休眠版本中已弃用,如果是这样,您也可以使用以下解决方案: 具有过滤复杂集的标准