使用HQL查询时,若是需要返回单张或多张表的部分信息,而不是返回全部信息时。
我们可以事先创建一个DTO(Data Transfer Object 数据传输对象),即一个中间实体类,用来存储我们查询出来的数据,通过 new XXX()这样的方式在HQL语句中使
用,前提是在XXX这个类中必须要有接受这些字段的构造方法才行,而且在new的时候必须使用类的全名。这样做的好处是不会暴露服务端表结构,同时返回的结果将不
在是一个Object[]数组,而是一个对象(可以通过get,set方便的取值和设值)。
创建的DTO:
package com.ezhiyang.shop.entity;
import java.io.Serializable;
public class HrAssets implements Serializable {
private static final long serialVersionUID = -8908193318769896828L;
private Long id;
private Long totalCount;
private Long spareCount;
private Long yuCount;
private String linkName;
private String gname;
private String agent;
private Boolean isUsed;
//无参的构造方法
public HrAssets() {
}
//与HQL查询想匹配的构造方法,用来存储获得的数据
public HrAssets(Long id,String linkName, String gname, String agent,Long totalCount, Long spareCount, Long yuCount) {
this.id = id;
this.linkName = linkName;
this.gname = gname;
this.agent = agent;
this.totalCount = totalCount;
this.spareCount = spareCount;
this.yuCount = yuCount;
}
public String getAgent() {
return agent;
}
public void setAgent(String agent) {
this.agent = agent;
}
public Long getTotalCount() {
return totalCount;
}
public void setTotalCount(Long totalCount) {
this.totalCount = totalCount;
}
public Long getSpareCount() {
return spareCount;
}
public void setSpareCount(Long spareCount) {
this.spareCount = spareCount;
}
public Long getYuCount() {
return yuCount;
}
public void setYuCount(Long yuCount) {
this.yuCount = yuCount;
}
public Boolean getIsUsed() {
return isUsed;
}
public void setIsUsed(Boolean isUsed) {
this.isUsed = isUsed;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLinkName() {
return linkName;
}
public void setLinkName(String linkName) {
this.linkName = linkName;
}
public String getGname() {
return gname;
}
public void setGname(String gname) {
this.gname = gname;
}
}
调用的类
package com.ezhiyang.shop.dao.impl;
import java.math.BigInteger;
import javax.persistence.FlushModeType;
import javax.persistence.TypedQuery;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Repository;
import com.ezhiyang.shop.commonentity.Page;
import com.ezhiyang.shop.commonentity.Pageable;
import com.ezhiyang.shop.dao.HrAssetsDao;
import com.ezhiyang.shop.dao.base.impl.BaseDaoImpl;
import com.ezhiyang.shop.entity.ElectronicCardExchangeCode;
import com.ezhiyang.shop.entity.FuliInOutRecord;
import com.ezhiyang.shop.entity.FuliInOutRecord.Type;
import com.ezhiyang.shop.entity.HrAssets;
import com.ezhiyang.shop.entity.Member;
import com.ezhiyang.shop.entity.MemberElectronicCardDetail;
@Repository("hrAssetsDaoImpl")
public class HrAssetsDaoImpl extends BaseDaoImpl
implements HrAssetsDao {
public Page
// TODO Auto-generated method stub
// 多表关联查询
if (pageable == null) {
pageable = new Pageable();
}
StringBuffer sql = new StringBuffer(
"SELECT COUNT(1) FROM "
+ "( SELECT e.id,COUNT(a.id) AS totals, "
+ "COUNT( CASE WHEN a.is_used = 0 THEN a.id END ) AS weishiyong, "
+ "COUNT( CASE WHEN a.is_used = 1 THEN a.id END) AS yishiyong "
+
"from zy_electronic_card_exchange_code a "
+ " LEFT JOIN zy_electronic_card b on a.electronic_card=b.id "
+ " LEFT JOIN zy_electronic_card_member c on c.electronic_card =a.electronic_card and c.electronic_card=b.id"
+ " LEFT JOIN xx_member d on c.member =d.id "
+ " LEFT JOIN xx_hr e on d.hr=e.id "
+ " LEFT JOIN zy_agent f on e.agent=f.id"
+ " WHERE b.activity_type=0 ");
if(!StringUtils.isEmpty(linkName)){
sql=sql.append(" and e.link_name like '%" + linkName + "%'");
}
if(!StringUtils.isEmpty(name)){
sql=sql.append(" and e.name like '%" + name + "%'");
}
if(!StringUtils.isEmpty(agentName)){
sql=sql.append(" and f.m_name like '%" + agentName + "%'");
}
sql.append(" GROUP BY e.id ) a ");
Object con = entityManager.createNativeQuery(sql.toString()).setFlushMode(FlushModeType.COMMIT).getSingleResult();
BigInteger total = (BigInteger) con;
int totalPages = (int) Math.ceil((double) total.doubleValue()
/ (double) pageable.getPageSize());
if (totalPages < pageable.getPageNumber()) {
pageable.setPageNumber(totalPages);
}
sql = new StringBuffer(
" SELECT new com.ezhiyang.shop.entity.HrAssets( " +
"e.id,e.linkName,e.name as gname,f.mName as agent,count(a.id) as totalCount ,sum(case WHEN a.isUsed = 0 THEN 1 else 0 END) as spareCount" +
",sum(case WHEN a.isUsed = 1 THEN 1 else 0 END) as yuCount ) from "
+ "ElectronicCardExchangeCode a,ElectronicCard b,MemberElectronicCard c,Member d,HR e "
+ "left join e.agent as f "
+ " where a.electronicCard=c.electronicCard and a.electronicCard=b.id " +
" and c.electronicCard=b.id "
+ "and c.member =d.id and d.hr=e.id and b.activityType=0 ");
if(!StringUtils.isEmpty(linkName)){
sql=sql.append(" and e.linkName like '%" + linkName + "%'");
}
if(!StringUtils.isEmpty(name)){
sql=sql.append(" and e.name like '%" + name + "%'");
}
if(!StringUtils.isEmpty(agentName)){
sql=sql.append(" and f.mName like '%" + agentName + "%'");
}
sql.append(" GROUP BY e.id ");
TypedQuery
HrAssets.class).setFlushMode(FlushModeType.COMMIT);
query.setFirstResult((pageable.getPageNumber() - 1)* pageable.getPageSize());
query.setMaxResults(pageable.getPageSize());
return new Page
pageable);
}
}
注:1、用StringBuffer方便语句拼接,便于添加条件;
2、对于count和sum的数据,在构造方法中一定在注意其类型,此处为Long若使用int或者Integer则会报错;
3、HQL是面相对象的,直接使用SQL中的case when 语句HQl是无法识别。可以使用如下方法解决。当然使用join也可以弄,这里使用CASE WHEN代码仅用一句SQL:
select 班级,count(case when 分数>=60 then 分数 else null end),count(case when 分数<60 then 分数 else null end)from 表 group by 班级;
这是问题来了,明明在MYSQL中能够正常得出结果,但是弄到HQL就不行了,会出错!
后面找了半天终于找到一个解决方法:
HQL:
select 班级,sum(case when 分数>=60 then 1 else 0end),sum(case when 分数<60 then 1 else 0 end) from 表group by 班级;
4、HQL使用left join的方式与SQL是不同的
from Cat
as
cat join cat.mate
as
mate left join cat.kittens
as
kitten
此处Cat为何实体类,mate为Cat实体类中定义的与其关联的另一个对象,也是一个实体类通过 join A.B的方式进行关联。还可以通过with增加更过的过滤条件:
from Cat
as
cat left join cat.kittens
as
kitten with kitten.bodyWeight > 10.0
引自: http://www.cnblogs.com/cyjch/archive/2012/03/14/2395340.html