http://www.cnblogs.com/kelin1314/archive/2010/09/09/1821897.html

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();

或者:
  1. StringBuffer queryStr = new StringBuffer();
  2. queryStr.append("select count(*) AA,");
  3. queryStr.append("sum(st.num1) BB,sum(st.num2) CC,");
  4. queryStr.append("max(st.cost1) DD,min(st.cost2) EE,");
  5. queryStr.append("st.col1 FF from TBXXX st")
  6. .append(" where ")
  7. .append(SQLQuerySetup.createfilterStr(filter))
  8. .append(" group by st.col1");
  9. query = session.createSQLQuery(queryStr.toString());
  10. query.addScalar("AA", new org.hibernate.type.IntegerType());
  11. query.addScalar("BB", new org.hibernate.type.IntegerType());
  12. query.addScalar("CC", new org.hibernate.type.IntegerType());
  13. query.addScalar("DD", new org.hibernate.type.IntegerType());
  14. query.addScalar("EE", new org.hibernate.type.IntegerType());
  15. query.addScalar("FF", new org.hibernate.type.IntegerType());
  16. return query.list();

注意2个问题 
1.Query 没有addScalar()方法,使用SQLQuery才有addScalar()方法 
2.如果查询的结果集的字段为id,count(*) as count,则如果只 
addScalar("count",type),将得不到id的值,需要加上addScalar("id",type),也就是要把每一个字段都要addScalar()

使用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查询相关推荐

  1. Hibernate SQL 查询

    本文转载自:https://www.cnblogs.com/li3807/p/6358386.html Hibernate 支持使用原生的SQL查询,使用原生SQL查询可以利用某些数据库特性,原生SQ ...

  2. hibernate SQL查询COUNT函数

    在Oracle11g中hibernate执行SQL语句使用COUNT聚合函数时,返回类型是BigDecimal 在MySQL5.5中COUNT聚合函数返回类型则是BigInteger 用其他类型数据接 ...

  3. Hibernate Native SQL查询示例

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

  4. Hibernate本机SQL查询示例

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

  5. hibernate的native sql查询

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

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

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

  7. Hibernate本地SQL查询SQLQuery

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

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

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

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

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

最新文章

  1. 2022-2028年中国超韧尼龙行业市场调查分析及未来前景分析报告
  2. php定义常量mypi 3.14,php – Codeigniter 3使用未定义的常量VIEWPATH – 假设’VIEWPATH’...
  3. JAVA实现https单向认证
  4. asp.net引用用户控件
  5. 关于ELMo,面试官们都怎么问
  6. java 桥梁模设计,Java设计模式学习篇(九)桥接设计模式
  7. 联想记忆计算机网络,什么是双向联想记忆神经网络
  8. UVA 624 CD (01背包 带路径)
  9. 关于PCB板热设计的学习总结
  10. GB 4208-93 外壳防护等级(IP代码)
  11. 京东在线客服话术汇总!
  12. 台式计算机2017排行分析,台式电脑CPU性能排行 桌面CPU天梯图2017年9月最新版 (全文)...
  13. 如何用python爬虫薅羊毛_拼多多现重大BUG被“薅羊毛”,教你如何用Python简单褥羊毛...
  14. CCNet: Criss-Cross Attention for Semantic Segmentation论文阅读
  15. idea保存快捷键_windows10下idea快捷键文件
  16. JDF代码学习 JDF入门教程 代码配置
  17. Pocket PC 基础知识
  18. ESP8266使用MQTT接入阿里IoT
  19. 2019年 支付宝集福攻略
  20. #数据结构与算法 第一小题 学生成绩档案管理系统

热门文章

  1. 【数据结构与算法】之深入解析“正则表达式匹配”的求解思路与算法示例
  2. iOS之深入解析高阶容器的原理和应用
  3. 2014/School_C_C++_A/5/勾股定理
  4. 64. Minimum Path Sum 最小路径和
  5. 这年头学爬虫还就得会点 scrapy 框架
  6. 征战蓝桥 —— 2014年第五届 —— C/C++A组第10题——波动数列
  7. 征战蓝桥 —— 2016年第七届 —— C/C++A组第2题——生日蜡烛
  8. 【STM32】GPIO相关函数和类型
  9. python取反函数_Python优雅的反函数int(string,base)
  10. linux 读写时间变长,linux时钟变慢的原因分析【转】