Hibernate查询之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,将有更好的性能表现。当然也可以没有该设定。
Hibernate查询之SQL查询的更多相关文章
- hibernate将本地SQL查询结果封装成对象
hibernate将本地SQL查询结果封装成对象 不知道大家有没有碰过这种情况,迫于很多情况只能用native SQL来查询(如:复杂统计等),然而使用native查询后,结果会被放到object里, ...
- hibernate使用原生SQL查询返回结果集的处理
今天没事的时候,看到公司框架里有一个用原生SQL写的函数,说实在以前自己也干过这事,但好久都没有用,都忘得差不多了,现在基本都是用的hql语句来查询结果.hibernate中使用createSQLQu ...
- 13.hibernate的native sql查询(转自xiaoluo501395377)
hibernate的native sql查询 在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hi ...
- Hibernate SQLQuery 原生SQL 查询及返回结果集处理-1
第一篇:官方文档的处理方法,摘自官方 在迁移原先用JDBC/SQL实现的系统,难免需要采用hibernat native sql支持. 1.使用SQLQuery hibernate对原生SQL查询执行 ...
- hibernate的native sql查询
在我们的hibernate中,除了我们常用的HQL查询以外,还非常好的支持了原生的SQL查询,那么我们既然使用了hibernate,为什么不都采用hibernate推荐的HQL查询语句呢?这是因为HQ ...
- hibernate 5原生sql查询测试学习代码
基本查询 import java.util.List; import org.hibernate.SQLQuery; import org.hibernate.Session; import org. ...
- Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?
Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?先上两种实现方式的实例:$querys["house_type_image"] ...
- hibernate在使用sql查询query自动转化成model类型数据,query.addEntity
hibernate使用自动的hql查询或者其封装的查询方法都能字段转化成对象 而如果在hibernate中使用sql时大多返回为Object[]对象 那么如何将object[]转换成model呢,答案 ...
- Hibernate 的原生 SQL 查询
Hibernate除了支持HQL查询外,还支持原生SQL查询. 对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取 ...
随机推荐
- python开发-web框架之diango-----Models
这篇博客是紧连上一篇博客的,因为内容较多,这里介绍的是Models这一部分的内容 七:Models 数据库的配置 1 django默认支持sqlite,mysql, oracle,postgre ...
- pyqt中使用matplotlib绘制动态曲线
一.项目背景: 看了matplotlib for python developers这本书,基本掌握了在pyqt中显示曲线的做法,于是自己写一个. 二.需求描述: 1)X轴显示时间点,显示长度为1分钟 ...
- c#中struct和class的区别 z
1.struct 是值类型,class是对象类型 2.struct 不能被继承,class可以被继承 3.struct 默认的访问权限是public,而class默认的访问权限是private. 4. ...
- avalon中require的实现
var plugins = { loader: function(builtin) { window.define = builtin ? innerRequire.define : otherDef ...
- delphi xe5 android 开发数据访问手机端(二)
界面就这样吧,继续...,先启动咱们上几片文章建立的手机服务端 导入webservices单元,file->new->other->webservices->选择 wsdlim ...
- python JSON处理
概念 序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON.XML等. 反序列化:就是从存储区域(JSON,XML)读取反序列化对象的 ...
- LCIS tyvj1071 DP优化
思路: f[i][j]表示n1串第i个与n2串第j个且以j结尾的LCIS长度. 很好想的一个DP. 然后难点是优化.这道题也算是用到了DP优化的一个经典类型吧. 可以这样说,这类DP优化的起因是发现重 ...
- [BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】
题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于 ...
- 利用MSF溢出攻击讲解
msf的强大之处也就不做探讨了,虽然这些东西网上很多.但我想说说我的感受. 这次的演示是在BT5中远程攻击一台win2003 sp2 metasploit是4.3的 需要说明的一点是 现在的BT5中不 ...
- Linux下fork()、vfork()、clone()和exec()的区别
转自Linux下fork().vfork().clone()和exec()的区别 前三个和最后一个是两个类型.前三个主要是Linux用来创建新的进程(线程)而设计的,exec()系列函数则是用来用指定 ...