第6章深入使用Hibernate 6.6 SQL查询

来源:互联网 发布:网络机顶盒免费vip软件 编辑:程序博客网 时间:2024/06/05 04:03

6.6 SQL查询

如果是一个新的应用,通常不要使用SQL查询。

SQL查询是通过SQLQuery接口来表示的。有如下方法:

*setFirstResult():设置返回结果集的起始点

*setMaxResult():设置查询获取的最大记录数

*list():返回查询到的结果集

*addEntity():将查询到的记录与特定的实体关联

*addScalar():将查询的记录关联成标量值

执行SQL查询的步骤如下:

1)获取Hibernate Session对象

2)编写SQL语句

3)以SQL语句作为参数,调用Session的createSQLQuery方法创建查询对象。

4)调用SQLQuery对象的addScalar()或addEntity()方法将选出的结果与标量值或实体进行关联,分别用于进行标量查询或实体查询

5)如果SQL语句包含参数,则调用Query的setXXX方法为参数赋值

6)调用Query的list方法返回查询的结果集

6.6.1 标量查询

通过addScalar()方法返回指定列和指定列的类型
session.createSQLQuery("select * from student_inf")
.addScalar("name",StandardBasicTypes.STRING)
.list();
例子:
//执行标量查询public void scalarQuery(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();String sqlString = "select stu.* from student_inf as stu";List l = session.createSQLQuery(sqlString)//指定查询name和student_id两个数据列.addScalar("name" , StandardBasicTypes.STRING).addScalar("student_id" , StandardBasicTypes.INTEGER)//返回标量值列表.list();for (Iterator it = l.iterator(); it.hasNext() ; ){//每个集合元素都是一个数组,数组元素是name、student_id两列值Object[] row = (Object[])it.next();System.out.println(row[0] + "\t" + row[1]);}tx.commit();HibernateUtil.closeSession();}

6.6.2 实体查询

将查询结果转化为实体,可以使用SQLQuery提供的多个重载的addEntity()方法。
//执行实体SQL查询public void entityQuery(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();String sqlString = "select * from enrolment_inf where year=:year";List l = session.createSQLQuery(sqlString)//指定将查询的记录行转换成Student实体.addEntity(Enrolment.class)//为SQL字符串的参数设置值.setInteger("year" , 2005).list();for (Iterator it = l.iterator(); it.hasNext() ; ){//每个集合元素都是一个Enrolment对象Enrolment e = (Enrolment)it.next();System.out.println(e.getStudent().getName() + "\t" + e.getCourse().getName());}tx.commit();HibernateUtil.closeSession();}
SQL语句可以选出多个数据表的数据,Hibernate也同样支持将查询结果转换成多个实体:
//执行返回多个实体的SQL查询public void multiEntityQuery(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();String sqlString = "select s.*,e.*,c.* "+ "from student_inf s,enrolment_inf e,course_inf c "+ "where s.student_id = e.student_id "+ "and e.course_code = c.course_code";List l = session.createSQLQuery(sqlString)//指定将查询的记录行转换成Student实体.addEntity("s", Student.class).addEntity("e", Enrolment.class).addEntity("c", Course.class).list();//提交事务,关闭Sessiontx.commit();HibernateUtil.closeSession();//因为数据已经全部被选出,故程序可以遍历列表中的数据for (Iterator it = l.iterator(); it.hasNext() ; ){//每个集合元素都是Student、Enrolment//和Course所组成的数组Object[] objs = (Object[])it.next();Student s = (Student)objs[0];Enrolment e = (Enrolment)objs[1];Course c = (Course)objs[2];System.out.println(s.getName() + "\t" + e.getYear() + "\t" + e.getSemester()+ "\t" + c.getName());}}
不仅如此,Hibernate还可将查询的结果转化为非持久化实体。
Query接口提供了一个setResultTransformer()方法,该方法可接受一个Transformers对象,通过使用该对象即可把查询到的结果集转化成JavaBean集。
//执行返回普通JavaBean的SQL查询public void beanQuery(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();String sqlString = "select s.name stuName, c.name courseName "+ "from student_inf s,enrolment_inf e,course_inf c "+ "where s.student_id = e.student_id "+ "and e.course_code = c.course_code ";List l = session.createSQLQuery(sqlString)//指定将查询的记录行转换成StudentCourse对象.setResultTransformer(Transformers.aliasToBean(StudentCourse.class)).list();//提交事务,关闭Sessiontx.commit();HibernateUtil.closeSession();//因为数据已经全部被选出,故程序可以遍历列表中的数据for (Iterator it = l.iterator(); it.hasNext() ; ){//每个集合元素都是StudentCourse对象StudentCourse sc = (StudentCourse)it.next();System.out.println(sc.getStuName() + "\t" + sc.getCourseName());}}

6.6.3 处理关联和继承

将关联实体转化成查询结果的方法是SQLQuery addJoin(String alias,String path),该方法第一个参数是转换后的实体名,第二个参数是待转换的实体属性。
//使用关联的原生SQL查询public void joinQuery(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();String sqlString = "select s.* , e.* from student_inf s , "+ "enrolment_inf e where s.student_id=e.student_id";List l = session.createSQLQuery(sqlString).addEntity("s", Student.class).addJoin("e" , "s.enrolments").list();//提交事务,关闭Sessiontx.commit();HibernateUtil.closeSession();//因为数据已经全部被选出,故程序可以遍历列表中的数据for (Iterator it = l.iterator(); it.hasNext() ; ){//每个集合元素都是Student、Enrolment组成的数组Object[] objs = (Object[])it.next();Student s = (Student)objs[0];Enrolment e = (Enrolment)objs[1];System.out.println(s.getName() + "\t" + e.getYear());}}

6.6.4 命名SQL查询

可以将SQL语句不放在程序中,而是放在配置文件中。
Hibernate使用<sql-query.../>元素来配置命名SQL查询,配置<sql-query.../>元素有一个必填的name属性,该属性用于指定该命名SQL查询的名称。包含一个或多个如下子元素:
*<return.../>:将查询结果转换为持久化实体
*<return-join.../>:预加载持久化实体的关联实体
*<return-scalar.../>:将查询的数据列转换成标量值
配置一个SQL查询片段:
<!-- 指定SQL查询的名称为queryTest --><sql-query name="queryTest"><!-- 将s别名转换成Student实体 --><return alias="s" class="Student"/><!-- 将e别名转换成Enrolment实体 --><return alias="e" class="Enrolment"/><!-- 预初始化e的course属性(关联实体) --><return-join alias="c" property="e.course"/><!-- 指定将student表的name列作为标量值返回 --><return-scalar column="s.name" type="string"/>select s.*,e.*,c.* from student_inf s,enrolment_inf e,course_inf c where s.student_id = e.student_id and e.course_code = c.course_codeand e.year=:targetYear</sql-query>
使用session的getNamedQuery即可获取指定命名SQL查询。
//执行命名SQL查询private void query(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();//调用命名查询,直接返回结果List l = session.getNamedQuery("queryTest").setInteger("targetYear" , 2005).list();tx.commit();HibernateUtil.closeSession();//遍历结果集for(Iterator it = l.iterator(); it.hasNext() ;){//每个集合元素是Student、Enrolment//和stuName三个元素的数组Object[] objs = (Object[])it.next();Student s = (Student)objs[0];Enrolment e = (Enrolment)objs[1];String stuName = (String)objs[2];System.out.println(s.getName() + "\t"+ e.getYear() + "\t" + e.getSemester()+ "\t=" + e.getCourse().getName() + "=\t" + stuName);}}
除此之外,Hibernate允许将结果集的映射信息放在<resultset.../>元素定义,这样就可以让多个命名查共用该结果集映射。通过为<sql-query.../>元素指定resultset-ref属性,就可让命名SQL查询使用一个已有的结果集映射了。

6.6.5 调用存储过程

Hibernate可以通过命名SQL查询来调用存储过程或函数。对于函数,该函数必须返回一个结果集;对于存储过程,该存储过程的第一个参数必须是传出参数,且其数据类型是结果集。
例子:
数据库中有一个存储过程:
create procedure select_all_student()
select *
from student_inf;
配置文件:
<!-- 定义一个调用存储过程的命名SQL查询 --><sql-query name="callProcedure" callable="true"><!-- 将查询结果转换成Student实体 --><return class="Student"><!-- 将查询的数据列转换成实体的属性 --><return-property name="studentNumber"column="student_id"/><return-property name="name" column="name"/></return>{call select_all_student()}</sql-query>
需要增加callable="true",还需要使用<return-property.../>子元素将指定列转换成实体的属性。
//调用存储过程private void callProcedure(){//打开Session和事务Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction();//调用命名查询,直接返回结果List l = session.getNamedQuery("callProcedure").list();tx.commit();HibernateUtil.closeSession();//遍历结果集for(Iterator it = l.iterator(); it.hasNext() ;){//每个集合元素是Student对象Student s = (Student)it.next();System.out.println(s.getName());}}

6.6.6 使用定制SQL

Hibernate允许在<class.../>元素以及系列映射集合的元素里使用<sql-insert.../>、<sql-delete.../>和<sql-update.../>等元素来指定定制SQL语句。
如果我们希望使用使用存储过程来执行插入、更新、修改等操作,则只需为<sql-insert.../>、<sql-delete.../>和<sql-update.../>指定callable="true"即可。
0 0
原创粉丝点击