技术总结(四)-Hibernate 多表查询

本文主要介绍了在工作中如何使用Hibernate进行多表查询,特别是针对查询特定时间段内用户每天访问不同企业的次数。通过LogEnt实体类举例,讨论了两种实现方式:执行原生SQL语句和使用HQL。虽然没有涉及分页功能,但提供了获取总记录数的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录一下工作中遇到的问题和解决办法。

最近遇到是一个问题就是通过Hibernate查询多个表,每个表中取几个字段。在这里记录一下解决的办法,和大家交流。

分割线

--------------------------------

一、先跟大家交代一下用到的实体类

LogEnt 记录用户访问企业实体

public class LogEnt{
     private String id;
     private String lcid;//访问企业id
     private String userId; //用户id
     private Date timestamp; //访问时间
}

User  用户

public class User{
      private String userId; //主键
      private String mobile; //手机号
      private String state;   //用户状态
      ...
}
实体都是只写了用到的属性。

二、实现功能

查询在选定的时间段内,用户每天访问的企业数量(不包括重复访问的企业)

三、思路

1、使用Hibernate执行原生sql语句查询多个表实现

2、创建一个包含所需要属性的实体,使用hql实现(界面所需要的属性  用户手机号、访问时间(精确到天)、每天访问次数),没有实现分页功能,使用hql语句查询总记录数


四、实现

(1)、使用Hibernate执行sql实现

//用户手机号、     开始时间、   结束时间、    访问次数
public Page observe(String mobile,String from,String to,String number,Page page){
           boolean flag = true;
           DetachedCriteria logEntCriteria = DetachedCriteria.forClass(LogEnt.class);
           String sql = "select  b.mobile,a.timestamp, count(DISTINCT a.lcid) from log_ent a,user b where a.userid = b.userId and b.state = '1' ";
//根据手机号查询用户Id
            if(!StringUtils.isEmpty(mobile)){
                DetachedCriteria dc = DetachedCriteria.forClass(User.class);
                dc.add(Restrictions. eq("mobile" , mobile));
                List<User> users = userDao.findAllByCriteriaSpecification(dc);
                 if(users!= null&&users.size()!=0){
                     User user = users.get(0);
                     logEntCriteria.add(Restrictions. eq("userId" , user.getUserId()));
                     sql = sql + " and  b.userId = '"+user.getUserId()+"' and  a.userid = '"+user.getUserId()+ "' ";
                } else{
//如果输入的手机号没有查询到用户,不执行查询
                     flag = false;
                }
           } else{
//如果没有传入手机号,则查询所有用户
                sql = sql + " and  b.userId = a.userid ";
           }
            if(!StringUtils.isEmpty(from)){
//toDate函数是给日期拼接上了 mysql的日期格式化函数,转化成对应的类型 
                sql+= " and a.timestamp >= "+toDate(from, "%Y-%m-%d");
           }
            if(!StringUtils.isEmpty(to)){
                sql+= " and a.timestamp <= "+toDate(to, "%Y-%m-%d");         
           }
           sql = sql + " GROUP BY a.timestamp";
            if(!StringUtils.isEmpty(number)){
                sql = sql + " HAVING COUNT(DISTINCT a.lcid) >="+Integer.parseInt (number)+"" ;
           }
	   //查询总数的sql
           String countSql = "select COUNT(*) from  ("+sql+") c";
           
            if(flag){
                Session session  = logDao.getSessionFactory().openSession();
                Query countquery  = session.createSQLQuery(countSql);
                BigInteger total  =  (BigInteger) countquery.uniqueResult();
                long result = total.longValue();
                long currentNumber = ((page.getPage()-1)*page.getRows()+page.getRows());
		//分页
                if(currentNumber>result){
                     sql = sql + " limit "+(page.getPage()-1)+","+(result-((page.getPage()-1)*page.getRows()))+ " ";
                }else{
			sql = sql + " limit "+(page.getPage()-1)+","+page.getRows()+" ";
		}
		//使用createSQLQuery 执行原生sql
                Query query = session.createSQLQuery(sql);
		//使用原生sql查询出来的结果,会放在一个Object[]数组中,顺序就是sql语句中的查询顺序
                List<Object[]> objectList = query.list();
                List<ObserveResult> list = new ArrayList<ObserveResult>();
                for(Object[] object:objectList){
                     ObserveResult or = new ObserveResult();
                     or.setMobile(object[0].toString());
                     or.setCudate((Date)object[1]);
		     //count(*)的查询结果对应的是BigInteger 类型
                     or.setCount(((BigInteger)object[2]).longValue());
                     list.add(or);
                }
                page.setList(list);
                page.setTotal(result);
                return page;              
           }
            return page;
     }



(2)、使用Hql 实现

创建的实体

public class ObserveResult{
      private String mobile;
      private Date cudate;
      private Long count;
      
      //必须具有构造方法
      public ObserveResult(String mobile,Date cudate,Long count){
      this.mobile = mobile;
      this.cudate = cudate;
      this.count = count;
      }
}

//和使用sql查询l逻辑类似
public Page observe(String mobile,String from,String to,String number,String type,Page page){
            boolean flag = true;
            DetachedCriteria logEntCriteria = DetachedCriteria.forClass(LogEnt.class);
            String hql = "select new com.entplus.home.entity.ObserveResult(b.mobile,a.timestamp,COUNT(DISTINCT a.lcid)) from LogEnt as a,User as b where a.userid = b.userId and b.state = '1' ";
            if(!StringUtils. isEmpty(mobile)){
                DetachedCriteria dc = DetachedCriteria.forClass(User.class);
                dc.add(Restrictions. eq("mobile" , mobile));
                List<User> users = userDao.findAllByCriteriaSpecification(dc);
                if(users!= null&&users.size()!=0){
                     User user = users.get(0);
                     logEntCriteria.add(Restrictions. eq("userId" , user.getUserId()));
                     hql = hql + " and  b.userId = '"+user.getUserId()+"' and  a.userid = '"+user.getUserId()+ "' ";
                } else{
                     flag = false;
                }
           } else{
                hql = hql + " and  b.userId = a.userid ";
           }
            if(!StringUtils. isEmpty(from)){ 
                hql+= " and a.timestamp >= "+toDate(from, "%Y-%m-%d");
           }
            if(!StringUtils. isEmpty(to)){
                hql+= " and a.timestamp <= "+toDate(to, "%Y-%m-%d");
           }
           hql = hql + " GROUP BY a.timestamp";
            if(!StringUtils. isEmpty(number)){
                hql = hql + " HAVING COUNT(DISTINCT a.lcid) >="+Integer.parseInt (number)+"" ;
           }

            if(flag){
	//未解决问题:因为hql不支持 from(子查询),所以没有查出记录的总记录数来,所以分页功能就没有实现
	  String countHql = "select COUNT(*) from  ("+hql+") c";
	//因为没有实现分页功能,所以把每页数据量设的足够大,让所有的数据在一页显示
	  page.setRows(1000); 
	 Query query = session.createQuery(hql).setMaxResults(page.getRows()).setFirstResult(( int) ((page.getPage()-1)*page.getRows())); 
	   Query query = session.createQuery(hql);   
//因为已经创建了对应的实体,所以Hibernate会自动的把数据填充到实体中
List<ObserveResult> list = query.list();
                page.setList(list);
                page.setTotal(list.size());
                return page;
           }
            return page;
    }



因为能力还有些不足,所以hql语句的分页功能没有能够实现,希望能够帮到大家。也希望有经验的朋友能够帮我解决遗留的一个问题。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值