Hibernate02-HQL查询语言

一、使用HQL语句操作数据库

Hibernate支持三种查询方式:HQL查询、Criteria查询及原生SQL(Native SQL)查询(本篇文章对HQL查询进行讲解)。

  • HQL(Hibernate Query Language,Hibernate查询语言)是一种面向对象的查询语言,其没有表和字段的概念,只有类、对象和属性的概念。

  • Criteria查询采用面向对象的方式构造查询。

  • 原生SQL查询就是直接执行SQL语句的查询,可以在SQL中利用不同数据库所特有的一些特性进行查询。例如数据库是Oracle,则可以使用Oracle的关键字或函数等。

1、编写HQL语句

HQL语句中除了Java类和属性的名称外,对大小写不敏感,所以SELECT和select是相同的,但是cn.hibernate.entity.Dept不等价于hibernate.entity.DEPT。HQL语句中的关键字建议使用小写字母,如select。

(1)form子句
Hibernate中最简单的HQL语句形式如下,以下几条HQL语句都用于查询所有部门。

例1: from cn.hibernatedemo.entity.Dept
说明: cn.hibernatedemo.entity.Dept 是全限定类名

例2: from Dept
说明: 类名Dept省略了包名

例3:

	from Dept as dept
	from Dept dept

说明: 以上两条HQL语句为持久化类Dept指派了别名dept,可以在HQL语句中使用这个别名;关键字as是可选的。

(2)select子句 :用于选取对象和属性

例1: select dept.deptName from Dept as dept;
说明: select子句选取了一个属性deptName,也可选取多个属性。

例2: elect dept from Dept as dept;
说明: select后跟的是别名dept

(3)where子句:用于表达查询的限制条件

例1: from Dept where deptName='SALES'
说明:

  • 该HQL语句用于查询名称是 SALES 的部门;
  • 在where子句中直接使用属性名deptName

例2: from Dept as dept where dept.deptName='SALES'
说明:

  • 该HQL语句用于查询名称是 SALES 的部门;
  • 在语句中指派了别名,在where子句中使用了完整的属性名dept.deptName

例3: from Dept dept where dept.loc is not null
说明: 这条HQL语句用于查询地址不为 null 的部门

(4)表达式:一般用在where子句中

例1: from Dept dept where lower(dept.deptName)='sales'
说明:

  • 该HQL语句用于查询名称是sales的部门,不区分大小写。
  • lower()函数用于把字符串中的每个字母改为小写

例2: from Emp where year(hireDate)=1980
说明:

  • 该HQL语句用于查询1980年入职的员工;
  • year()函数用于获取日期字段的年份

(5)order by子句:用于按指定属性排序

例1: from Emp order by hireDate asc
说明:

  • 该HQL语句用于查询所有员工,并按员工入职时间升序排序
  • 关键字asc或desc为可选,默认asc升序排序

例2: from Emp order by hireDate,salary deac

说明: 该HQL语句用于查询所有员工,先按员工入职时间升序排序,入职时间相同的再按员工工资降序排序。

2、使用Query对象执行HQL语句

(1)使用list()方法获取所有数据

Emp实体类

/**
 * 员工类
 */
public class Emp {

    /**
     * 员工编号
     */
    private Integer empNo;


    /**
     * 员工姓名
     */
    private String ename;

    /**
     * 员工职位
     */
    private String job;

    /**
     * 上级编号
     */
    private Integer mgr;

    /**
     * 入职日期
     */
    private Date hiredate;

    /**
     * 工资
     */
    private Double sal;

    /**
     * 福利
     */
    private Double comm;

    /**
     * 部门编号
     */
    private Integer deptNo;
	
	//省略getter/setter方法

}

Emp.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="cn.demo.po.Emp" table="EMP" schema="scott" dynamic-update="true">
        <id name="empNo" type="java.lang.Integer" column="EMPNO">
            <!--为了避免主键生成器assigned造成的干扰,把主键生成器 替换为increment-->
            <generator class="assigned"/>
        </id>
        <property name="ename" type="java.lang.String" column="ENAME"/>
        <property name="deptNo" type="java.lang.Integer" column="DEPTNO"/>
        <property name="mgr" type="java.lang.Integer" column="MGR"/>
        <property name="job" type="java.lang.String" column="JOB"/>
        <property name="sal" type="java.lang.Double" column="SAL" />
        <property name="comm" type="java.lang.Double" column="COMM" />
        <property name="hiredate" type="java.util.Date" column="HIREDATE"/>
    </class>
</hibernate-mapping>

注意配置完成后需要在hibernate.cfg.xml中做映射

	<!--映射文件配置,注意文件名必须包含其相对于classpath的全路径-->
	<mapping resource="cn/demo/dao/emp/Emp.hbm.xml"/>

EmpDao.java


public class EmpDao extends BaseDao{
	/**
     * 查询所有员工:使用Query对象的list()方法
     * @return
     */
    public List<Emp> findAll(){
        //定义HQL语句
        String hql="from Emp";
        //构建Query对象
        Query query=currentSession().createQuery(hql);
        //执行查询
        return query.list();
    }
}

EmpBiz.java

public class EmpBiz {

    private EmpDao empDao=new EmpDao();

    /**
     * 获取所有员工信息
     * @return 员工列表
     */
    public List<Emp> findAllEmps(){
        Transaction tx=null;
        List<Emp> emps=null;
        try {
            //开始事务
            tx=empDao.currentSession().beginTransaction();
            emps=empDao.findAll();  //调用list()方法进行持久化操作
            tx.commit();    //提交事务
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();  //回滚事务
            }
        }
        return emps;
    }
}

测试类

 	/**
     * 测试获取所有员工信息方法
     */
    @Test
    public void test1(){
        //使用list()方法获取所有员工信息
       	List<Emp> empList=new EmpBiz().findAllEmps();
        //遍历并输出结果
        for (Emp emp:empList){
            System.out.println("员工姓名:"+emp.getEname());
        }
    }

运行结果
Hibernate02-HQL查询语言

(2)使用iterate()方法获取所有数据

EmpDao.java

public class EmpDao extends BaseDao {

	public Iterator<Emp> findAll1(){
		 //定义HQL语句
        String hql="from Emp";
        //构建Query对象
        Query query=currentSession().createQuery(hql);
        return query.iterate();
    }
}

EmpBiz.java

public class EmpBiz {

    private EmpDao empDao=new EmpDao();

    /**
     * 获取所有员工信息
     * @return
     */
    public Iterator<Emp> findAllEmps(){
        Transaction tx=null;
        Iterator<Emp> emps=null;
        try {
            //开始事务
            tx=empDao.currentSession().beginTransaction();
            //调用itertate()方法查询所有
            emps=empDao.findAll1(); 
            //遍历并输出结果,与调用list()方法时不同,需在会话关闭前测试查询结果
            Emp emp=null;
            while(emps.hasNext()){
                emp=emps.next();
                System.out.println("员工姓名:"+emp.getEname());
            }
            tx.commit();    //提交事务
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();  //回滚事务
            }
        }
        return emps;
    }
}

测试类

	@Test
    public void test1(){
       //调用itertate()方法查询所有员工
        Iterator<Emp> empIterator=new EmpBiz().findAllEmps();
    }

注意运行结果

Hibernate: 
    select
        emp0_.EMPNO as col_0_0_ 
    from
        scott.EMP emp0_
Hibernate: 
    select
        emp0_.EMPNO as EMPNO3_0_,
        emp0_.ENAME as ENAME3_0_,
        emp0_.DEPTNO as DEPTNO3_0_,
        emp0_.MGR as MGR3_0_,
        emp0_.JOB as JOB3_0_,
        emp0_.SAL as SAL3_0_,
        emp0_.COMM as COMM3_0_,
        emp0_.HIREDATE as HIREDATE3_0_ 
    from
        scott.EMP emp0_ 
    where
        emp0_.EMPNO=?
员工姓名:SMITH
Hibernate: 
    select
        emp0_.EMPNO as EMPNO3_0_,
        emp0_.ENAME as ENAME3_0_,
        emp0_.DEPTNO as DEPTNO3_0_,
        emp0_.MGR as MGR3_0_,
        emp0_.JOB as JOB3_0_,
        emp0_.SAL as SAL3_0_,
        emp0_.COMM as COMM3_0_,
        emp0_.HIREDATE as HIREDATE3_0_ 
    from
        scott.EMP emp0_ 
    where
        emp0_.EMPNO=?
员工姓名:ALLEN
Hibernate: 
    select
        emp0_.EMPNO as EMPNO3_0_,
        emp0_.ENAME as ENAME3_0_,
        emp0_.DEPTNO as DEPTNO3_0_,
        emp0_.MGR as MGR3_0_,
        emp0_.JOB as JOB3_0_,
        emp0_.SAL as SAL3_0_,
        emp0_.COMM as COMM3_0_,
        emp0_.HIREDATE as HIREDATE3_0_ 
    from
        scott.EMP emp0_ 
    where
        emp0_.EMPNO=?
员工姓名:WARD
Hibernate: 
    select
        emp0_.EMPNO as EMPNO3_0_,
        emp0_.ENAME as ENAME3_0_,
        emp0_.DEPTNO as DEPTNO3_0_,
        emp0_.MGR as MGR3_0_,
        emp0_.JOB as JOB3_0_,
        emp0_.SAL as SAL3_0_,
        emp0_.COMM as COMM3_0_,
        emp0_.HIREDATE as HIREDATE3_0_ 
    from
        scott.EMP emp0_ 
    where
        emp0_.EMPNO=?
员工姓名:JONES

说明:

  • 从Hibernate生成的sql语句可以看出,list()方法生成一条sql查询语句,查询
    所有符合条件的记录;
  • iterate()方法首先查询出所有符合条件的主键值,此处是empno,然后在需要
    某一对象的其他属性值时,才生成按主键查询的sq语句,此处是
	select * from emp where empno=?

即iterate()方法可能生成1+n条sql语句。

小结:执行HQL语句的步骤

  • 获取session对象
  • 编写hql语句
  • 创建query对象
  • 执行查询,得到查询结果

二、在HQL语句与绑定参数

1、HQL语句的参数绑定

(1)按参数位置绑定

在HQL语句中用“?”占位符来定义参数的位置,形式如下

Query query=session.createQuery("from Emp where job=? and salary>?"); 

以上HQL语句中定义了两个参数,可以通过setXXX()方法来绑定参数,参数位置下标从0开始:

	query.setString(0,job);
	query.setDouble(1,salary);

Query对象提供了绑定各种类型参数的方法,setInteger()等等

例:

	 /**
     * 根据部门名称查找部门
     * @param deptName
     * @return
     */
    public List<Dept> findByDeptName(String deptName){
        String hql="from Dept as dept where dept.dName=?";
        Query query=currentSession().createQuery(hql);
        query.setString(0,deptName);	//绑定参数,下标从0开始
        return query.list();
    }

(2)按参数名称绑定

在HQL语句中可以定义命名参数,命名参数以“:”开头,形式如下

	Query query=currentSession().
			createQuery("from Emp where job=:empJob and sal>:empSalary");

说明:

  • 以上HQL语句定义了两个 命名参数 empJob和empSalary
  • 接下来调用Query对象的setXXX()方法来绑定参数
	query.setString("empJob",empJob);
	query.setDouble("empSalary",empSalary);

Query对象提供了绑定各种类型参数的setXXX()方法的重载,第一个参数代表命名参数的名称,第二个参数代表命名参数的值。

例:

	/**
     * 根据部门名称查找部门
     * @param deptName
     * @return
     */
    public List<Dept> findByDeptName(String deptName){

        //按参数名称绑定
        String hql="from Dept as dept where dept.dName=:name";
        Query query=currentSession().createQuery(hql);
        query.setString("name",deptName);//为命名参数赋值
        return query.list();
    }	

按名称绑定与按位置绑定相比有以下优势:

  • (1)使程序代码有较好的可读性
  • (2)按名称绑定的形式有利于程序代码的维护。对于按位置绑定的形式,如果参数在HQL语句中的位置改变了,就必须修改相关绑定参数的代码。此种方式削弱了程序代码的健壮性和可维护性。

2、绑定不同数据类型的参数

(1)Query接口提供的绑定不同数据类型参数的方法

  • setBoolean():绑定类型为java.lang.Boolean的参数
  • setByte():绑定类型为java.lang.Byte的参数
  • setDouble():绑定类型为java.lang.Double的参数
  • setDate():绑定类型为java.util.Date的参数
  • setString():绑定类型为java.lang.String的参数

以上每个方法都有两种重载形式,如setString()方法

  • setString(int position,String val):按位置绑定参数
  • setString(String name,String val):按名称绑定参数

除了以上用于绑定特定类型的参数方法,Hibernate还提供了 setParameter()方法 ,用于绑定任意类型的参数。该方法使用Object类型作为HQL参数的类型,当不变指定参数的具体类型时,可以使用setParameter()为参数赋值。
例:

EmpDao.java


public class EmpDao extends BaseDao{

	 /**
     * 根据条件查询员工:使用setParameter()方法
     * @param conditions
     * @return
     */
    public List<Emp> findByConditions(Object[] conditions){
        //查询依赖多个条件,且类型各异
        String hql="from Emp where job=? and sal>?";
        Query query=currentSession().createQuery(hql);
        //判断条件参数是否为空
        if(conditions!=null&&conditions.length>0){
            //若不为空则遍历数组绑定参数值
            for (int i=0;i<conditions.length;i++){
                //这里下标从0开始
                query.setParameter(i,conditions[i]);    //为占位符赋值
            }
        }
        return  query.list();
    }

}

EmpBiz.java

public class EmpBiz{

	private EmpDao empDao=new EmpDao();
	
	/**
     * 根据条件查询员工:使用setParameter()方式
     * @param conditions
     * @return
     */
    public List<Emp> findByConditions(Object[] conditions){
        Transaction tx=null;
        List<Emp> emps=null;
        try {
            tx=empDao.currentSession().beginTransaction();
            emps=empDao.findByConditions(conditions);
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return  emps;
    }
}

测试类

	/**
     * 根据条件获取emps:使用setParameter()方式
     */
    @Test
    public  void test2(){
        //查询条件
        Object[] conditions={"CLERK",1000.0};
        List<Emp> empList=new EmpBiz().findByConditions(conditions);
        //遍历并输出结果
        for (Emp emp:empList){
            System.out.println("员工姓名:"+emp.getEname());
        }
    }

运行结果
Hibernate02-HQL查询语言

(2)setProperties()方法:绑定命名参数与一个对象的属性值

EmpDao.java

public class EmpDao extends BaseDao{

	 /**
     * 根据条件获取Emp:使用setProperties()方法
     * @param conditions
     * @return
     */
    public List<Emp> findByConditions(Emp conditions){
        //=:后面的为命名参数,命名参数必须与对象的属性名一致
        String hql="from Emp where job=:job and sal>:sal";
        Query query=currentSession().createQuery(hql);
        //根据命名参数的名称,从conditions中获取相应的属性值进行赋值
        query.setProperties(conditions);
        return query.list();
    }	
}

说明: setProperties()方法为命名参数赋值,使用Emp对象封装了条件,命名参数和Emp类的相关属性相匹配。

EmpBiz.java

public class EmpBiz{

	private EmpDao empDao=new EmpDao();

	 /**
     * 根据条件获取员工信息列表:使用setProperties()方式
     * @param conditions
     * @return
     */
    public List<Emp> findByConditions(Emp conditions){

        Transaction tx=null;
        List<Emp> empList=null;
        try {
            tx=empDao.currentSession().beginTransaction();
            empList=empDao.findByConditions(conditions);
            tx.commit();
        }catch (HibernateException ex){
            ex.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return empList;
    }
}

测试类

 	 /**
     * 多条件获取emps:使用setProperties()方式
     */
    @Test
    public void test3(){
        Emp conditions=new Emp();
        conditions.setJob("SALESMAN");
        conditions.setSal(1000.0);
        List<Emp> empList=new EmpBiz().findByConditions(conditions);
        //遍历并输出结果
        for (Emp emp:empList){
            System.out.println("员工姓名:"+emp.getEname());
        }
    }

执行结果
Hibernate02-HQL查询语言

3、Hibernate动态设置查询参数的方式

需求:根据员工职位Job、工资>某数,入职时间在某个日期段的信息列表;三个条件可以随意组合,所以在条件数不确定的情况下,可以使用Hibernate提供的动态设置查询参数的方式。下面创建一个类用于封装查询条件:

EmpCondition.java


/**
 * 封装员工表查询条件
 */
public class EmpCondition {

    private String job; //员工职位
    private Double salary;  //工资
    private Date hireDateEnd;   //员工入职结束时间
    private Date hireDateStart; //员工入职起始时间
	
	//省略getter/setter方法
}

因为涉及日期类型的数据处理,所以创建一个工具类用于转换日期格式

stringToDateConverter.java


/**
 * 字符串转换日期类型
 */
public class stringToDateConverter {

    /**
     * 将字符串转换为日期类型
     * @param dateStr  日期字符串
     * @param pattern  转换格式
     * @return 日期对象
     */
    public static Date strToDate(String dateStr,String pattern)throws Exception{
        //设置日期格式
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat(pattern);
        //将String类型的日期转换为java.util.Date
        return simpleDateFormat.parse(dateStr);
    }
}

EmpDao.java

	/**
     * 多条件动态查询emps
     * @param hql
     * @param empCondition
     * @return
     */
    public List<Emp> findByConditions(String hql, EmpCondition empCondition){

        return currentSession().createQuery(hql).   //创建Query对象
                setProperties(empCondition).        //为参数赋值
                list();     //执行查询,获取查询结果
    }

EmpBiz.java

    /**
     * 多条件动态查询emps
     * @param empCondition
     * @return
     */
    public List<Emp> findByConditions(EmpCondition empCondition){

        Transaction tx=null;
        List<Emp> empList=null;
        try {
            //开启事务
            tx=empDao.currentSession().beginTransaction();
            //HQL根据条件动态生成
            StringBuffer hql=new StringBuffer("from Emp as emp where 1=1");
            //判断职位是否为空
            if (empCondition.getJob()!=null&&empCondition.getJob().length()>0){
                hql.append(" and emp.job=:job");
            }
            //判断薪资条件是否为空
            if (empCondition.getSalary()!=null&&empCondition.getSalary()!=0){
                hql.append(" and emp.sal>:salary");
            }
            //判断入职日期大于某个日期
            if(null!=empCondition.getHireDateStart()){
                hql.append(" and emp.hiredate>:hireDateStart");
            }
            //判断入职日期小于某个日期
            if(null!=empCondition.getHireDateEnd()){
                hql.append(" and emp.hiredate<:hireDateEnd");
            }
            //执行查询
            empList=empDao.findByConditions(hql.toString(),empCondition);
            //提交事务
            tx.commit();
        }catch (HibernateException ex){
            ex.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return empList;
    }

测试类

   /**
     * 动态绑定多条件参数查询emps
     */
    @Test
    public void test4(){
        EmpCondition empCondition=new EmpCondition();
        empCondition.setJob("CLERK");
        empCondition.setSalary(1000.0);
        try {
            empCondition.setHireDateStart(stringToDateConverter.strToDate("1981-4-1","yyyy-MM-dd"));
            //empCondition.setHireDateEnd(stringToDateConverter.strToDate("1985-9-9","yyyy-MM-dd"));
        }catch (Exception e){
            e.printStackTrace();
        }
        List<Emp> empList=new EmpBiz().findByConditions(empCondition);
        //遍历并输出结果
        for (Emp emp:empList){
            System.out.println("员工姓名:"+emp.getEname());
        }
    }

运行结果

Hibernate02-HQL查询语言

4、使用Hibernate API之uniqueResult()方法

上面例子中使用Query接口的list()、iterate()方法可以获取集合,还可以通过uniqueResult()方法获取唯一结果。

EmpDao.java

	/**
     * 获取薪资>=范围的员工数:使用Query对象的uniqueResult(),该方法返回唯一结果
     * @param sal
     * @return
     */
    public Long obtainTheRowCount(Double sal){
        String hql="select count(id) from Emp where sal>=:sal";
        return (Long)currentSession().createQuery(hql).
                setDouble("sal",sal).   //设置参数
                uniqueResult();     //执行返回唯一结果,以Object类型封装
    }

EmpBiz.java

  
  public Long countBySalary(Double sal){
        Transaction tx=null;
        Long result=null;
        try{
            tx= empDao.currentSession().beginTransaction();
            result=empDao.obtainTheRowCount(sal);
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return result;
    }

测试类

    /**
     * 测试Query的uniqueResult()方法返回唯一结果
     */
    @Test
    public  void test5(){
        Double sal=1000.0;
        Long result=new EmpBiz().countBySalary(sal);
        System.out.println("薪资:"+sal+"以上的员工人数有:"+result+"人");
    }

运行结果
Hibernate02-HQL查询语言

三、实现分页和投影查询

1、Hibernate分页查询API

Hibernate通过使用Query接口的以下两个方法实现分页:

  • setFirstResult(int firstResult):用于设置需要返回的第一条记录的位置,下标从0开始。
  • setMaxResults(int maxResults):用于设置最大返回记录数。

例:
EmpDao.java

    /**
     * 分页获取数据
     * @param pageNo  当前页数
     * @param pageSize 每页显示记录数
     * @return
     */
    public List<Emp> findByPage(int pageNo,int pageSize){
        return currentSession().createQuery("from Emp order by id").
                setFirstResult((pageNo-1)*pageSize).    //设置获取结果的起始下标
                setMaxResults(pageSize).    //设置每页显示记录数
                list(); //执行查询
    }

EmpBiz.java


	/**
     * 分页获取emps
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<Emp> findEmpByPage(int pageNo,int pageSize){

        Transaction tx=null;
        List<Emp> empList=null;
        try {
            tx=empDao.currentSession().beginTransaction();
            empList=empDao.findByPage(pageNo,pageSize);
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return empList;
    }

测试类

  	/**
     * 测试分页获取员工信息
     */
    @Test
    public void test6(){
        int pageNo=2;
        int pageSize=4;
        List<Emp> empList=new EmpBiz().findEmpByPage(pageNo,pageSize);
        //遍历并输出结果
        for (Emp emp:empList){
            System.out.println("员工姓名:"+emp.getEname());
        }
    }

运行结果
Hibernate02-HQL查询语言

2、Hibernate投影查询API

有时数据展示并不需要获取对象的全部属性,而是只需要对象的某一个或某几个
属性,或者需要通过表达式、聚合函数等方式得到某些结果,此时可以使用投影查询。投影查询需要使用HQL的select子句。对于投影结果的封装,有以下3种常见情况:

- (1)每条查询结果仅包含一个结果列

DeptDao.java

    /**
     * 获取所有部门名称
     * @return String集合
     */
    public List<String> findAllNames(){
        String hql="select dName from Dept";
        return currentSession().createQuery(hql).list();
    }

DeptBiz.java

  	/**
     * 获取所有部门名称
     * @return
     */
    public List<String> findAllNames(){
        Transaction tx=null;
        List<String> result=null;
        try {
            tx=deptDao.currentSession().beginTransaction();
            result=deptDao.findAllNames();
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return result;
    }

测试类:


    /**
     * 使用投影查询获取所有部门名称
     */
    @Test
    public void test7(){
        List<String> result=new DeptBiz().findAllNames();
        for(String str:result){
            System.out.println(str);
        }
    }

运行结果

Hibernate02-HQL查询语言
- (2)每条查询结果包含不止一个结果列

DeptDao.java

  	/**
     * 获取所有部门信息:返回多行多列
     * @return
     */
    public List<Object[]> findAllDeptList(){
        String hql="select deptNo,dName from Dept";
        return currentSession().createQuery(hql).list();
    }

说明: 以上方法为获得所有部门的编号与名称。查询结果集合中的每个元素都是对象数组Object[],数组的长度为2,数组的第一个元素是部门编号,第二个元素是部门名称。这种方式一般只应用于查询部分属性值时,注意数组下标与属性值的对应。

DeptBiz.java

  	/**
     * 获取所有部门信息:返回多行多列
     * @return
     */
    public List<Object[]> findAllDeptList(){
        Transaction tx=null;
        List<Object[]> result=null;
        try {
            tx=deptDao.currentSession().beginTransaction();
            result=deptDao.findAllDeptList();
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return result;
    }

测试类


    /**
     * 测试:使用投影API返回多行多列
     */
    @Test
    public void test8(){
        List<Object[]> list=new DeptBiz().findAllDeptList();
        //遍历集合
        for(int i=0;i<list.size();i++){
            Object[] object=list.get(i);    //取出每一个对象数组Object[]
            //遍历数组:数组第一个下标对应部门编号,第二个编号对应部门名称
            for(int j=0;j<object.length;j++){
                System.out.println(object[j]);
            }
        }
    }

运行结果
Hibernate02-HQL查询语言

- (3)将某条查询结果通过构造方法封装成对象

DeptDao.java

 	/**
     * 将每条查询结果通过构造方法封装成对象
     * @return
     */
    public List<Dept> findDeptList(){
        String hql="select new Dept(deptNo,dName) from Dept";
        return currentSession().createQuery(hql).list();
    }

注:Dept.java中需要存在无参/带参构造方法

DeptBiz.java


 	/**
     * 将每条查询结果通过构造方法封装成对象
     * @return
     */
    public List<Dept> findDeptList(){
        Transaction tx=null;
        List<Dept> result=null;
        try {
            tx=deptDao.currentSession().beginTransaction();
            result=deptDao.findDeptList();
            tx.commit();
        }catch (HibernateException e){
            e.printStackTrace();
            if(tx!=null){
                tx.rollback();
            }
        }
        return result;
    }

测试类


    /**
     * 测试投影API 将查询结果通过构造方法封装为对象
     */
    @Test
    public void test9(){
        List<Dept> list=new DeptBiz().findDeptList();
        for(Dept dept:list){
            System.out.println("部门编号:"+dept.getDeptNo());
            System.out.println("部门名称:"+dept.getdName());
        }
    }

运行结果
Hibernate02-HQL查询语言