`
newleague
  • 浏览: 1483137 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

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

 

或者:
  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.   
  10. query = session.createSQLQuery(queryStr.toString());   
  11. query.addScalar("AA", new org.hibernate.type.IntegerType());   
  12. query.addScalar("BB", new org.hibernate.type.IntegerType());   
  13. query.addScalar("CC", new org.hibernate.type.IntegerType());   
  14. query.addScalar("DD", new org.hibernate.type.IntegerType());   
  15. query.addScalar("EE", new org.hibernate.type.IntegerType());   
  16. query.addScalar("FF", new org.hibernate.type.IntegerType());   
  17. 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,将有更好的性能表现。当然也可以没有该设定。

 

http://blog.csdn.net/dknypxt/archive/2010/07/18/5744389.aspx

分享到:
评论

相关推荐

    hibernate实现动态SQL查询

    hibernate实现动态SQL查询,通过XML配置SQL,FREEMARKER 解析,生成要执行的SQL

    Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法

    Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQL...

    Hibernate查询练习小例子

    利用MYSQL数据库提供的样例数据库world建立的查询小例子。已经建立好了数据库对应的...本项目主要是为了练习使用Hibernate查询数据库。如果有什么问题可以发站内信或者邮件asddf14@hotmail.com。我会尽量解答一下~~~

    Hibernate 函数 ,子查询 和原生SQL查询

    Hibernate 函数 ,子查询 和原生SQL查询。Hibernate 函数 ,子查询 和原生SQL查询

    Hibernate+本地SQL查询SQLQuery宣贯.pdf

    在某些情况下,开发者可能需要使用原生SQL查询来执行特定的数据库操作,这时就可以利用Hibernate的SQLQuery功能。本文将详细讲解如何使用Hibernate的SQLQuery进行本地SQL查询。 首先,创建SQLQuery实例是通过...

    hibernate数据库通用SQL代码

    查询数据的方法有两种实现,一种是基于HQL(Hibernate Query Language),另一种是基于原生SQL。 - 基于HQL的通用查询: HQL是Hibernate提供的面向对象的查询语言,可以方便地操作对象和属性。`select`方法接收一个...

    hibernate将本地SQL查询结果封装成对象(最终)

    使用本地sql语句查询后,无需再使用Object对查询结果进行强制转换,而是直接将查询结果放到实体Bean里了。 PS: 其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在...

    hibernate将本地SQL查询结果封装成对象

    hibernate将本地SQL查询结果封装成对象。如进行复杂的统计等本地sql语句查询后,直接放到对象里了,而不会再使用Object进行强转

    hibernate执行原生sql语句

    然而,在一些情况下,我们需要直接执行原生 SQL 语句,而不是使用 Hibernate 的查询语言(HQL)。本文将介绍如何使用 Hibernate 执行原生 SQL 语句。 为什么需要执行原生 SQL 语句 在实际开发中,我们可能需要执行...

    让hibernate输出sql语句参数配置.doc

    hibernate.dialect 是一个 Hibernate Dialect 类名,允许 Hibernate 针对特定的关系数据库生成优化的 SQL。其取值为 full.classname.of.Dialect。 2. hibernate.show_sql hibernate.show_sql 参数用于输出所有 SQL...

    Hibernate中Sql语句

    hibernate中使用sql 而不是hql语句

    Hibernate SQLQuery 本地查询

    NULL 博文链接:https://mlxnle.iteye.com/blog/1766676

    Ajax+Spring+Hibernate sql

    Ajax+Spring+Hibernate sql Ajax+Spring+Hibernate sql Ajax+Spring+Hibernate sql Ajax+Spring+Hibernate sql Ajax+Spring+Hibernate sql Ajax+Spring+Hibernate sql

    使用hibernate对sqlserver 2005进行增删改查

    在Java开发中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者通过面向对象的方式来操作数据库,而无需直接编写SQL语句。在这个场景中,我们将探讨如何使用Hibernate与SQL Server 2005数据库进行...

    Hibernate生产SQL语句

    模仿Hibernate生产SQL语句,使用Java反射

    hibernate sql query.pdf

    hibernate sql hqlsql

    Hibernate中的查询:HQL、Criteria、原生SQl

    Hibernate中的查询:HQL、Criteria、原生SQl的Demo,希望可以帮助大家理解Hibernate查询。

    hibernate 多表查询

    hibernate 多表查询 hibernate 多表不同于一般的sql嵌套查询,嵌套查询是不支持的,所以必须要配置好才能实现多表!只要配置好了,还是特别好用的

    Hibernate+本地SQL查询SQLQuery.pdf

    《Hibernate中的本地SQL查询SQLQuery》 在Java的持久化框架Hibernate中,有时我们需要使用原生的SQL查询来实现特定的数据库操作,这时就需要利用到SQLQuery接口。本篇文章将详细解析如何使用Hibernate的SQLQuery来...

    hibernate将本地SQL查询结果封装成对象(最终).zip

    hibernate将本地SQL查询结果封装成对象(最终).zip

Global site tag (gtag.js) - Google Analytics