4.5 SQL查询

Hibernate还支持使用SQL查询,使用SQL查询可以利用某些数据库的特性,或者用于将原有的JDBC应用迁移到Hibernate应用上。使用命名的SQL查询还可以将SQL语句放在配置文件中配置,从而提高程序的解耦,命名SQL查询还可以用于调用存储过程。

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

SQL查询是通过SQLQuery接口来表示的,SQLQuery接口是Query接口的子接口,因此完全可以调用Query接口的方法:

● setFirstResult(),设置返回结果集的起始点。

● setMaxResults(),设置查询获取的最大记录数。

● list(),返回查询到的结果集。

但SQLQuery比Query多了两个重载的方法:

● addEntity,将查询到的记录与特定的实体关联。

● addScalar,将查询的记录关联成标量值。

执行SQL查询的步骤如下:

(1)获取Hibernate Session对象;

(2)编写SQL语句;

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

(4)如果SQL语句包含参数,调用Query的setXxx方法为参数赋值;

(5)调用SQLQuery对象的addEntity或addScalar方法将选出的结果与实体或标量值关联;

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

看下面的SQL查询示例:

private void test()

{

//获取Hibernate Session对象

Session session = HibernateUtil.currentSession();

//开始事务

Transaction tx = session.beginTransaction();

//编写SQL语句

String sqlString = "select {s.*} from student s where s.name like '马军'";

//以SQL语句创建SQLQuery对象

List l = session.createSQLQuery(sqlString)

//将查询到的记录与特定实体关联起来

.addEntity("s",Student.class)

//返回全部的记录集

.list();

//遍历结果集

Iterator it = l.iterator();

while (it.hasNext())

{

//因为将查询结果与Student类关联,因此返回的是Student集合

Student s = (Student)it.next();

Set enrolments = s.getEnrolments();

Iterator iter = enrolments.iterator();

while(iter.hasNext())

{

Enrolment e = (Enrolment)iter.next();

System.out.println(e.getCourse().getName());

}

}

//提交事务

tx.commit();

//关闭Session

HibernateUtil.closeSession();

}

上面的示例显示了将查询记录关联成一个实体的示例。事实上,SQL查询也支持将查询结果转换成标量值,转换成标量值可以使用addScalar方法,如:

Double max = (Double) session.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")

.addScalar("maxWeight", Hibernate.DOUBLE);

.uniqueResult();

使用SQL查询,如果需要将查询到的结果转换成特定实体,就要求为选出的字段命名别名。这别名不是随意命名的,而是以“/”实例名.属性名“/”的格式命名,例如:

//依次将多个选出的字段命名别名,命名别名时都以ss作为前缀,ss是关联实体的别名

String sqlStr = "select stu.studentId as {ss.studentNumber},"

+ "stu.name as {ss.name} from "

+ "student as stu where stu.name like '杨海华'";

List l = session.createSQLQuery(sqlStr)

//将查询出的ss实例,关联到Student类

.addEntity("ss",Student.class)

.list();

在第一个示例中,以{s.*}代表该表的全部字段,且关联实例的别名也被指定为s。

注意:如果不使用{s.*}的形式,就可让实体别名和表别名互不相同。关联实体的类型时,被关联的类必须有对应的setter方法。

4.5.1 命名SQL查询

可以将SQL语句不放在程序中,而放在配置文件中,这种方式以松耦合的方式配置SQL语句,可以提高程序解耦。

在Hibernate的映射文件中定义查询名,然后确定查询所用的SQL语句,然后就可以直接调用该命名SQL查询。在这种情况下,不需要调用addEntity()方法,因为在配置命名SQL查询时,已经完成了查询结果与实体的关联。

下面是命名SQL查询的配置片段:

<!-- 每个sql-query元素定义一个命名SQL查询 -->

<sql-query name="mySqlQuery">

<!-- 关联返回的结果与实体类 -->

<return alias="s" class="Student"/>

<!-- 定义命名SQL查询的SQL语句 -->

SELECT {s.*}

from student s WHERE s.name like'杨海华'

</sql-query>

sql-query元素是hibernate-mapping元素的子元素。因此,sql-query定义的名可以直接通过Session访问,上面定义的mySqlQuery查询可以直接访问,下面是使用该命名SQL查询的示例代码:

private void testNamedSQl()

{

//获取Hibernate Session对象

Session session = HibernateUtil.currentSession();

//开始事务

Transaction tx = session.beginTransaction();

//调用命名查询,直接返回结果

List l = session.getNamedQuery("mySqlQuery")

.list();

//遍历结果集

Iterator it = l.iterator();

while (it.hasNext())

{

//在定义SQL查询时,已经将结果集与Student类关联起来

//因此,集合里的每个元素都是Student实例

Student s = (Student)it.next();

Set enrolments = s.getEnrolments();

Iterator iter = enrolments.iterator();

while(iter.hasNext())

{

Enrolment e = (Enrolment)iter.next();

System.out.println("=====================================");

System.out.println(e.getCourse().getName());

System.out.println("=====================================");

}

}

tx.commit();

HibernateUtil.closeSession();

}

4.5.2 调用存储过程

Hibernate 3增加了存储过程的支持,该存储过程只能返回一个结果集。

下面是Oracle 9i的存储过程示例:

CREATE OR REPLACE FUNCTION selectAllEmployments

RETURN SYS_REFCURSOR

AS

st_cursor SYS_REFCURSOR;

BEGIN

OPEN st_cursor FOR

SELECT EMPLOYEE, EMPLOYER,

STARTDATE, ENDDATE,

REGIONCODE, EID, VALUE, CURRENCY

FROM EMPLOYMENT;

RETURN st_cursor;

END;

如果需要使用该存储过程,可以先将其定义成命名SQL查询,例如:

<!-- 定义命名SQL查询,name属性指定命名SQL查询名 -->

<sql-query name="selectAllEmployees_SP" callable="true">

<!-- 定义返回列与关联实体类属性之间的映射 -->

<return alias="emp" class="Employment">

<!-- 依次定义每列与实体类属性的对应 -->

<return-property name="employee" column="EMPLOYEE"/>

<return-property name="employer" column="EMPLOYER"/>

<return-property name="startDate" column="STARTDATE"/>

<return-property name="endDate" column="ENDDATE"/>

<return-property name="regionCode" column="REGIONCODE"/>

<return-property name="id" column="EID"/>

<!-- 将两列值映射到一个关联类的组件属性 -->

<return-property name="salary">

<!-- 映射列与组件属性之间的关联 -->

<return-column name="VALUE"/>

<return-column name="CURRENCY"/>

</return-property>

</return>

{ ? = call selectAllEmployments() }

</sql-query>

调用存储过程还有如下需要注意的地方:

● 因为存储过程本身完成了查询的全部操作,所以调用存储过程进行的查询无法使用setFirstResult()/setMaxResults()进行分页。

● 存储过程只能返回一个结果集,如果存储过程返回多个结果集,Hibernate将仅处理第一个结果集,其他将被丢弃。

● 如果在存储过程里设定SET NOCOUNT ON,将有更好的性能表现。当然也可以没有该设定。

转载于:https://www.cnblogs.com/jadmin/archive/2009/07/19/2206097.html

Hibernate的SQL查询相关推荐

  1. Hibernate Native SQL查询示例

    Hibernate Native SQL查询示例 欢迎使用Hibernate Native SQL Query示例教程.我们在前面的文章中研究了Hibernate查询语言和Hibernate Crit ...

  2. Hibernate:SQL查询 addScalar()或addEntity()

      Hibernate除了支持HQL查询外,还支持原生SQL查询. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口.该 ...

  3. Hibernate本地SQL查询SQLQuery

    http://callan.iteye.com/blog/156127 使用SQLQuery 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQu ...

  4. 使用HIBERNATE的SQL查询并将结果集自动转换成POJO

    在某些场合下,我们可能想使用HIBERNATE的框架提供的SQL查询接口,但是,由于实体没有做映射,HIBERNATE不能把结果集转换成你想要的List<POJO>,本文讨论如何在这种情况 ...

  5. Hibernate原生SQL查询

    最近在做一个较为复杂的查询,hibernate基本的查询不能满足,只好使用其提供的原生sql查询.参考网上的一些资料,做一些总结. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行 ...

  6. informix的char字段类型通过hibernate的sql查询仅返回第一个字符之本人解决方法

    刚刚开始一个项目,后台数据库用informix,准备采用ssh的框架,框架搭建完在今天测试的过程中,发现表字段为char类型的时候,通过下面的查询语句,获取到的值总是只有第一个字符: SQLQuery ...

  7. Hibernate本机SQL查询示例

    Welcome to the Hibernate Native SQL Query example tutorial. We looked into Hibernate Query Language ...

  8. hibernate的native sql查询

    在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQ ...

  9. Hibernate sql查询

    http://www.cnblogs.com/kelin1314/archive/2010/09/09/1821897.html Hibernate还支持使用SQL查询,使用SQL查询可以利用某些数据 ...

  10. Hibernate事实:始终检查Criteria API SQL查询

    Criteria API对于动态构建查询非常有用,但这是我使用它的唯一用例. 每当您有一个带有N个过滤器且可以以任意M个组合到达的UI时,就应该有一个API动态地构造查询,因为连接字符串始终是我所不愿 ...

最新文章

  1. Nutanix 将社区版代码带入云中
  2. IBM公司扩展云平台 计划推出SmartCloud
  3. 重磅 | 带学斯坦福CS231n计算机视觉课+带打全球顶级kaggle大赛
  4. 关于:程序兼容多种数据库
  5. arm-linux cannot find -lgcc_s,arm-linux-gcc编译avrdude时报错: cannot find -lncurses
  6. 使用iconfont阿里多色矢量图标
  7. NeoKylin-Server使用docker部署跨主机redis集群
  8. 乔纳森 刘易斯 oracle,阿泰刘易斯都是幻想 专家点火箭引援之真命天子
  9. 退款单号在微信支付申请退款中的重要性
  10. 本地时间 与 UTC 时间 相互转化
  11. python爬虫 获取学信网 学校与对应专业信息
  12. fastjson按照ascii码排序
  13. MATLAB数字信号处理(2)LFM脉冲雷达回波处理仿真
  14. windows installer正准备安装
  15. outlook删除服务器文件夹,如何还原已删除的Outlook文件夹[最佳方式]
  16. 【Python】200行的文字RPG游戏
  17. 小区物业管理系统(数据库课程设计)
  18. VMware Player 5.0 NAT-DHCP 端口映射
  19. 做好5步操作,轻松写出一篇价值10万的软文
  20. 键盘--外语键盘问题

热门文章

  1. 神经网络中常用激活函数总结【Python实现激活函数与导函数,曲线可视化分析】
  2. linux asp.net 性能优化,ASP.NET性能优化之减少请求
  3. php web browser,如何在PHP Scriptable Web Browser中調用javascript函數
  4. 关于Stringbuffer的需要注意的几点
  5. 造梦西游外传服务器维护,造梦西游外传V3.5.9版本更新公告 “无限火力”限时开放...
  6. multisim变压器反馈式_【鼎阳硬件智库原创|高速总线】 以太网变压器反转问题技术分析...
  7. Leetcode之最长公共前缀
  8. wps中将文档输出为pdf_罗永浩点赞WPS超级会员功能:转化PDF是神操作
  9. 阿里云服务器centos7 安装docker 和docker-compose 及相关命令
  10. MyBatis 持久化框架快速使用入门(Xml配置版)