下面讲述HQL一些比较高级的应用,包括如何使用HQL查询继承关系数据、绑定参数和在配置文件中使用查询语句。
6.2.1 查询类及其所有继承的类的实例
默认情况下,当查询一个类时,Hibernate会自动搜索这个类的所有继承类。假如有如下3个类,类的关系如图6-7所示。
图6-7 Animal类及其子类Bird和Mammal
当调用如下HQL语句时,会查询出所有的Animal实例、Bird实例和Mammal实例。
from Animal
所有的类均继承自java.lang.Object,所以下面的HQL语句查询所有的类的对象实体,即查询所有映射表的记录。
from java.lang.Object
6.2.2 限制每次查询的返回对象数
Query接口提供了两个函数,用于限制每次查询返回的对象数。
SetFirstResult(int firstResult) 用于设置从哪一个对象开始检索。参数firstResult设置开始检索的起始记录。
setMaxResults(int maxResults) 用于设置每次检索返回的最大对象数。参数maxResults用于设置每次检索返回的对象数目。
这两个函数结合起来用,经常用于分页显示对象。例如数据库中有10000条记录,如果一次性显示实在太多,就可以进行分页显示。
下面的程序当每次循环时,从Student实例中检索出pageSize个对象,并输出到控制台,是一个典型的分页显示程序。
/**
* 分页输出对象
* @param pageSize 每页显示的记录条数
*/
public void pagenate(int pageSize)
{
Session session=HibernateSessionFactory.currentSession(); //创建Session
String hql="from Student"; //检索Student实例的HQL语句
String hql1="select count(*) from Student"; //检索出表中有多少条记录的HQL语句
Query q=session.createQuery(hql1); //创建Query
List list=q.list(); //执行查询
int count=((Integer)list.get(0)).intValue();//总的对象个数
int pageCount=(count+pageSize-1)/pageSize; //总的页数
Query query=session.createQuery(hql); //创建检索Student的查询
for(int i=0;i<pageCount;i++){
query.setFirstResult(i*pageSize);
query.setMaxResults(pageSize);
List list1=query.list(); //执行查询
Iterator it=list1.iterator();
System.out.println("***************************");
while(it.hasNext()){
Student stu=(Student)it.next();
System.out.println(stu.getId()+"\t"
+stu.getSno()+"\t"
+stu.getSname()+"\t"
+stu.getSsex()+"\t"
+stu.getSage()+"\t"
+stu.getSdept()+"\t"
+stu.getSaddress()
);
}
}
}
pagenate(int pageSize) 函数对指定的对象实例循环查询,每次循环检索出pageSize个对象。
HQL语句select count(*) from Student检索出学生对象的个数,把对象个数存入到变量count中。
用(count+pageSize-1)/pageSize计算出总的页数。
每次for循环时输出一页的记录。
6.2.3 绑定参数
使用绑定参数可以在程序运行时动态决定一些参数的值。下面比较不使用绑定参数和使用绑定参数时的情况。
第4章的4.3.6节中,ViewLog.java中有一个检索指定时间段日志的HQL语句:
String HQL="from Contents where logdate>='"+beginDate+" 00:00:00' and logdate<= '"+endDate+" 00:00:00'";
上述做法存在以下缺陷。
代码的可读性比较差。
安全性问题,用户可能执行别的代码或存在SQL注入式攻击。
性能低下。
查询语句中以“:”开头的变量叫做命名参数,把命名参数和一个具体的值进行绑定的过程叫做绑定参数。如下面的程序。
//声明hql语句,待绑定的参数以":"开头
String hql="from Student where sname=:name and sage>:age"; //name和age为命名参数
Query query=session.createQuery(hql); //创建查询
query.setParameter("name","李晓梅"); //进行绑定
query.setParameter("age",new Integer(20));
List list=query.list(); //执行查询
对上述代码说明如下。
“:name”指定了命名参数name,“:age”指定了命名参数age。
调用Query接口的setParameter()为命名参数赋一固定值。第一个参数指定参数名称,第二个参数指定参数值。当明确知道参数类型时,则可以使用相应的方法,例如参数为int型,可以使用setInteger()方法;参数为String型,可以使用setString()方法。
可以使用按照参数位置对参数进行绑定,如下面的代码所示。
String hql="from Student where sname=? and sage>?"; //声明hql语句,命名参数用“?”代替
Query query=session.createQuery(hql); //创建查询
query.setParameter(0,"李晓梅"); //绑定参数
query.setParameter(1,new Integer(20));
List list=query.list(); //执行查询
在HQL语句中用问号“?”代替命名参数。此时setParameter()函数的第一个参数指定参数的位置(position),0为HQL查询语句中的第一个参数,1为第二个参数,以此类推。
6.2.4 在映射文件配置HQL语句
为了使程序具有更大的灵活性,Hibernate可以在映射文件中配置HQL语句。如下所示为在Student.hbm.xml中的配置。
<hibernate-mapping>
<class name="hibernate.ch06.Student" table="student" catalog="joblog">
<!--此处省略了配置-->
</class>
<query name="searchStudent"><![CDATA[
from Student s where s.sage>22
]]>
</query>
</hibernate-mapping>
可以用如下代码访问配置文件中的HQL语句。
Session session=HibernateSessionFactory.currentSession();//创建Session
Query query=session.getNamedQuery("searchStudent"); //用getNamedQuery得到查询
List list=query.list(); //执行查询
Iterator it=list.iterator();
while(it.hasNext()){
Student stu=(Student)it.next();
System.out.println(stu.getSname());
}
6.2.1 查询类及其所有继承的类的实例
默认情况下,当查询一个类时,Hibernate会自动搜索这个类的所有继承类。假如有如下3个类,类的关系如图6-7所示。
图6-7 Animal类及其子类Bird和Mammal
当调用如下HQL语句时,会查询出所有的Animal实例、Bird实例和Mammal实例。
from Animal
所有的类均继承自java.lang.Object,所以下面的HQL语句查询所有的类的对象实体,即查询所有映射表的记录。
from java.lang.Object
6.2.2 限制每次查询的返回对象数
Query接口提供了两个函数,用于限制每次查询返回的对象数。
SetFirstResult(int firstResult) 用于设置从哪一个对象开始检索。参数firstResult设置开始检索的起始记录。
setMaxResults(int maxResults) 用于设置每次检索返回的最大对象数。参数maxResults用于设置每次检索返回的对象数目。
这两个函数结合起来用,经常用于分页显示对象。例如数据库中有10000条记录,如果一次性显示实在太多,就可以进行分页显示。
下面的程序当每次循环时,从Student实例中检索出pageSize个对象,并输出到控制台,是一个典型的分页显示程序。
/**
* 分页输出对象
* @param pageSize 每页显示的记录条数
*/
public void pagenate(int pageSize)
{
Session session=HibernateSessionFactory.currentSession(); //创建Session
String hql="from Student"; //检索Student实例的HQL语句
String hql1="select count(*) from Student"; //检索出表中有多少条记录的HQL语句
Query q=session.createQuery(hql1); //创建Query
List list=q.list(); //执行查询
int count=((Integer)list.get(0)).intValue();//总的对象个数
int pageCount=(count+pageSize-1)/pageSize; //总的页数
Query query=session.createQuery(hql); //创建检索Student的查询
for(int i=0;i<pageCount;i++){
query.setFirstResult(i*pageSize);
query.setMaxResults(pageSize);
List list1=query.list(); //执行查询
Iterator it=list1.iterator();
System.out.println("***************************");
while(it.hasNext()){
Student stu=(Student)it.next();
System.out.println(stu.getId()+"\t"
+stu.getSno()+"\t"
+stu.getSname()+"\t"
+stu.getSsex()+"\t"
+stu.getSage()+"\t"
+stu.getSdept()+"\t"
+stu.getSaddress()
);
}
}
}
pagenate(int pageSize) 函数对指定的对象实例循环查询,每次循环检索出pageSize个对象。
HQL语句select count(*) from Student检索出学生对象的个数,把对象个数存入到变量count中。
用(count+pageSize-1)/pageSize计算出总的页数。
每次for循环时输出一页的记录。
6.2.3 绑定参数
使用绑定参数可以在程序运行时动态决定一些参数的值。下面比较不使用绑定参数和使用绑定参数时的情况。
第4章的4.3.6节中,ViewLog.java中有一个检索指定时间段日志的HQL语句:
String HQL="from Contents where logdate>='"+beginDate+" 00:00:00' and logdate<= '"+endDate+" 00:00:00'";
上述做法存在以下缺陷。
代码的可读性比较差。
安全性问题,用户可能执行别的代码或存在SQL注入式攻击。
性能低下。
查询语句中以“:”开头的变量叫做命名参数,把命名参数和一个具体的值进行绑定的过程叫做绑定参数。如下面的程序。
//声明hql语句,待绑定的参数以":"开头
String hql="from Student where sname=:name and sage>:age"; //name和age为命名参数
Query query=session.createQuery(hql); //创建查询
query.setParameter("name","李晓梅"); //进行绑定
query.setParameter("age",new Integer(20));
List list=query.list(); //执行查询
对上述代码说明如下。
“:name”指定了命名参数name,“:age”指定了命名参数age。
调用Query接口的setParameter()为命名参数赋一固定值。第一个参数指定参数名称,第二个参数指定参数值。当明确知道参数类型时,则可以使用相应的方法,例如参数为int型,可以使用setInteger()方法;参数为String型,可以使用setString()方法。
可以使用按照参数位置对参数进行绑定,如下面的代码所示。
String hql="from Student where sname=? and sage>?"; //声明hql语句,命名参数用“?”代替
Query query=session.createQuery(hql); //创建查询
query.setParameter(0,"李晓梅"); //绑定参数
query.setParameter(1,new Integer(20));
List list=query.list(); //执行查询
在HQL语句中用问号“?”代替命名参数。此时setParameter()函数的第一个参数指定参数的位置(position),0为HQL查询语句中的第一个参数,1为第二个参数,以此类推。
6.2.4 在映射文件配置HQL语句
为了使程序具有更大的灵活性,Hibernate可以在映射文件中配置HQL语句。如下所示为在Student.hbm.xml中的配置。
<hibernate-mapping>
<class name="hibernate.ch06.Student" table="student" catalog="joblog">
<!--此处省略了配置-->
</class>
<query name="searchStudent"><![CDATA[
from Student s where s.sage>22
]]>
</query>
</hibernate-mapping>
可以用如下代码访问配置文件中的HQL语句。
Session session=HibernateSessionFactory.currentSession();//创建Session
Query query=session.getNamedQuery("searchStudent"); //用getNamedQuery得到查询
List list=query.list(); //执行查询
Iterator it=list.iterator();
while(it.hasNext()){
Student stu=(Student)it.next();
System.out.println(stu.getSname());
}