Criteria查询结果集Distinct解决方案

798 查看

最近在做一个项目用到了DetachedCriteria,但在查询的时候遇到了一些问题。现把问题总结下,和大家分享下学习心得。

我想从User中查询前三条数据出来,代码如下
DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
criteria.add(Restrictions.ge("registerTime", new Date()));
List<User> ulist = ht.findByCriteria(criteria, 0, 3);

但是查询出来的结果有重复的对象。

于是我加了下面一行代码:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) 

加完后,没有出现出现重复数据,但是,问题又来了,查询出来的结果不对。数据库符合条件的数据有三条,但是查询出来的结果有一条数据为null。

纠结半天,最后我把criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)改成了criteria.setProjection(Projections.distinct(Projections.property("id")));解决问题。

采用Projections.distinct(Projections.property("id"))来去重查询,返回的结果是List<String> 而不是 List<User>。

**总结:**
Criteria的结果集最常用分两种:对象List、List<Object[]>(投影查询),这两种查询结果的distinct处理的方式也是不一样的。

Criteria通过setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)方法对查询后结果进行排重,请注意,这种方式是先查询出可能重复的记录然后根据每个对象的equals方法进行排重,如果不需要分页,而且你的查询结果集很小的话,可以使用这种方式distinct结果集。

**warning:**
1. 要排重的对象要实现equals方法。
2. 不能进行分页处理,因为是先查询后distinct,结果会不准确。
3. 查询处理的结果集太大的话,可能存在性能问题,相同记录会查询多次。 

Criteria通过设置projectionList就可以只查询指定字段。

 **warning:**
Criteria投影查询出来的结果集格式是这样的:List<Object[]> 前台遍历集合的时候需要使用数组下标访问数据。

*如有不对之处,欢迎修改指正~*