记录一下工作中遇到的问题和解决办法。
最近遇到是一个问题就是通过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;
}
创建的实体
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语句的分页功能没有能够实现,希望能够帮到大家。也希望有经验的朋友能够帮我解决遗留的一个问题。