hibernate(jpa)根据实体动态生成查询条件,并实现分页问题的解决方案

hibernate如何根据传进去实体的不为空属性生成动态查询,并实现分页,经过查看hibernate api需要用到Criteria ,但是Criteria 有个缺点就是当另一个表A中某一外键列是该表B的主键,如果A表中有两条记录对应B表的某一主键,则查询结果中B表的该记录也会变为两条,我感到很不理解!最后从网上得知可以用 .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);去掉重复的结果,但实验之后我发现该语句只在提交的时候(也就是crit.list();的时候)才会去掉重复的结果,而分页的数据获取是在crit.list();之前,也就是说分页是在有重复数据的情况下根据起始位置获取的数据,显然是不正确的。后来又得知可以用crit .setProjection(Projections .projectionList()
 .add(Projections .distinct(Projections .id()))
的方法获得不重复的主键ID,可是Projections 只能指定属性,无法获得实体,最后只能用Projections 先获得id和创建时间(因为这里是按照创建时间排序的,所以查询结果中必须有创建时间),然后再根据ID查询实体,用 .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);去掉重复的结果;

 

List<ContentInfo> result = (List<ContentInfo>) getHibernateTemplate()
     .execute(new HibernateCallback() {
      public Object doInHibernate(Session arg0)
        throws HibernateException, SQLException {


       ContentInfo ci = new ContentInfo();
       BUtil.QueryContentBean2ContentInfo(ci, instance);

//根据实体创建Example 
       Example example = Example.create(ci)
         .excludeZeroes().ignoreCase() // perform
                 .enableLike(); // use like for string

            

       Criteria crit = arg0.createCriteria(
         ContentInfo.class).add(example).addOrder(
         Order.desc("createtime"));
       // .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
           // 查询出满足查询条件的内容的不重复id和创建时间
   
       crit .setProjection(Projections .projectionList()
           .add(Projections .distinct(Projections .id()))
           .add(Projections .property("createtime")));

       // 设置分页的信息
       crit.setFirstResult(PageUtil.getStart(currPage,
         pageSize));
       crit.setMaxResults(pageSize);
       List contentList = crit.list();

//提取出满足查询条件的内容的不重复id

       if (contentList != null
         && contentList.isEmpty() == false) {
        List contentId = new ArrayList();
        for (Object ob : contentList) {
         Object[] obs = (Object[]) ob;
         contentId.add(obs[0]);
        }
        // 通过内容id再取出内容实体

        Criteria crit2 = arg0.createCriteria( ContentInfo.class)
          .add( Restrictions.in("contentid",contentId)).addOrder( Order.desc("createtime"))
          .setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY);
        List<ContentInfo> results = (List<ContentInfo>) crit2 .list();
        log.debug("find by example successful, result size: "+ results.size());
        return results;


       } else {
        return null;
       }

      }
     });

 

 

注意:

如果实体的主键不为空是不参与动态生成查询条件;

如果实体的属性中有Long类型的,不要让它为0,要为null,否则就会生成查询条件where 属性***=0所以有些时候你都不知道为什么查询出来的结果为空。当然在这里是可以控制,在生成example 的时候添加excludeZeroes(),就把0排斥了,但这样带来的缺点就是,如果你将某一个Long类型的属性设为0,期望动态生成where 属性***=0就不可能了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值