- 设置 multiselect 无效问题
xxxxDao.findAll(Specifications.where(new Specification<XXBean>() {
@Override
public Predicate toPredicate(Root<XXBean> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
query.multiselect(root.get("a"),root.get("b"));
return null;
}
}));
上面的那段代码中multiselect的这是是无效的,这个问题当时很是困扰,到网上搜索很多人都遇到这个问题,但是也没有找到一个确切的答案,无奈只好自己debug代码了。终于找到了根源:
protected TypedQuery<T> getQuery(Specification<T> spec, Sort sort) {
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<T> query = builder.createQuery(getDomainClass());
Root<T> root = applySpecificationToCriteria(spec, query);
query.select(root);
if (sort != null) {
query.orderBy(toOrders(sort, root, builder));
}
return applyRepositoryMethodMetadata(em.createQuery(query));
}
上边这两句代码:
Root<T> root = applySpecificationToCriteria(spec, query);
query.select(root);
,第一句内部调用了toPredicate 接口执行了我们设置的multiselect ,然而第二句直接重置了查询的字段为表的所有字段.导致我们设置的查询字段无效。刚开始我认为这个hibernate的一个bug,但是后来想想他这样做也是为了预防另外一个bug的产生:分页查询的时候hibernate会自动生成一个count的sql,如果这时你设置了select字段,而且还有group by语句,group的字段为select的某一个字段。这时生成的count语句就有可能会出错了,select count(*) from table group by field ,这句sql可能会因为找不到field而出错。所以hibernate 这里直接不允许程序员在这里设置select字段也是有一定意义的。
当然了如果你不得不使用multiselect的这个功能,也是有办法的:通过entityManager 自己创建查询count,以及list,然后组装bean
long count = (long) entityManager.createQuery("select count (distinct b.openId) from BidPartin b ,BidUser u where b.openId=u.openId and b.bidId=" +bidPartin.getBidId()).getSingleResult();
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<BidPartinVo> cq = cb.createQuery(BidPartinVo.class);
Root<BidPartin> root = cq.from(BidPartin.class);
Predicate predicate = cb.conjunction();
predicate.getExpressions().add(cb.equal(root.get("bidId"),bidPartin.getBidId()));
cq.select(cb.construct(BidPartinVo.class
,cb.count(root.get("id")).alias("bidNum")
,root.get("bidId").alias("bidId")
,root.get("openId").alias("openId")
,cb.max(root.<BigDecimal>get("bidPrice")).alias("bidPrice")
,cb.max(root.<Long>get("createDate")).alias("createDate")
)).where(predicate).groupBy(root.get("openId"));
final List<BidPartinVo> voList = entityManager.createQuery(cq)
.setFirstResult(pageRequest.getOffset())
.setMaxResults(pageRequest.getPageSize())
.getResultList();
- join语句报错问题
在查询数据的时候需要join其他表查询,所以写了关联查询,但是一直报join出错,很是纠结。到网上查询得知,如果hql语句中用到了join,那么join的两个实体类中必须存在@manyToOne、oneToMany.....这样的关系才可以..否则是通不过的。如果必须要join而且实体中还没有这样的关系的话,只能通过select a from ABean a , BBean b where ...这种方式,或者直接写nativeSql了。
后期如果遇到其他问题了再继续更新。欢迎大家把各自遇到的一些问题拿来在这里讨论.