关于hibernate jpa 踩过的一个个坑

 

  1. 设置 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();

 

  1. join语句报错问题

          在查询数据的时候需要join其他表查询,所以写了关联查询,但是一直报join出错,很是纠结。到网上查询得知,如果hql语句中用到了join,那么join的两个实体类中必须存在@manyToOne、oneToMany.....这样的关系才可以..否则是通不过的。如果必须要join而且实体中还没有这样的关系的话,只能通过select a from ABean a , BBean b where ...这种方式,或者直接写nativeSql了。

 

 

 

 

     后期如果遇到其他问题了再继续更新。欢迎大家把各自遇到的一些问题拿来在这里讨论.

 

 

 

 

 

转载于:https://my.oschina.net/xiwanglr/blog/792962

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值