[size=large][/size]Native SQL查询
你也可以使用你的数据库的Native SQL语言来查询数据。这对你在要使用数据库的某些特性的时候(比如说在查询提示或者Oracle中的 CONNECT关键字),这是非常有用的。这就能够扫清你把原来直接使用SQL/JDBC 的程序迁移到基于 Hibernate应用的道路上的障碍。
Hibernate3允许你使用手写的sql来完成所有的create,update,delete,和load操作(包括存储过程)
17.1. 创建一个基于SQL的Query
SQL查询是通过SQLQuery接口来控制的,它是通过调用Session.createSQLQuery()方法来获得
List cats = sess.createSQLQuery("select {cat.*} from cats cat")
.addEntity("cat", Cat.class);
.setMaxResults(50);
.list();
这个查询指定了:
SQL查询语句,它带一个占位符,可以让Hibernate使用字段的别名.
查询返回的实体,和它的SQL表的别名.
addEntity()方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。
addJoin()方法可以被用于载入其他的实体和集合的关联,TODO:examples!
原生的SQL查询可能返回一个简单的标量值或者一个标量和实体的结合体。
Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")
.addScalar("maxWeight", Hibernate.DOUBLE);
.uniqueResult();
17.2. 别名和属性引用
上面使用的{cat.*}标记是 "所有属性" 的简写.你可以显式地列出需要的字段,但是你必须让Hibernate 为每一个属性注入字段的别名.这些字段的站位符是以字段别名为前导,再加上属性名.在下面的例子里,我们从一个其他的表(cat_log) 中获取Cat对象,而非Cat对象原本在映射元数据中声明的表.注意我们甚至在where子句中也可以使用属性别名. 对于命名查询,{}语法并不是必需的.你可以在第 17.3 节 “命名SQL查询”得到更多的细节.
String sql = "select cat.originalId as {cat.id}, " +
"cat.mateid as {cat.mate}, cat.sex as {cat.sex}, " +
"cat.weight*10 as {cat.weight}, cat.name as {cat.name} " +
"from cat_log cat where {cat.mate} = :catId"
List loggedCats = sess.createSQLQuery(sql)
.addEntity("cat", Cat.class)
.setLong("catId", catId)
.list();
注意:如果你明确地列出了每个属性,你必须包含这个类和它的子类的属性! and its subclasses!
17.3. 命名SQL查询
可以在映射文档中定义查询的名字,然后就可以象调用一个命名的HQL查询一样直接调用命名SQL查询.在这种情况下,我们不 需要调用addEntity()方法.
<sql-query name="mySqlQuery">
<return alias="person" class="eg.Person"/>
SELECT person.NAME AS {person.name},
person.AGE AS {person.age},
person.SEX AS {person.sex}
FROM PERSON person WHERE person.NAME LIKE 'Hiber%'
</sql-query>
List people = sess.getNamedQuery("mySqlQuery")
.setMaxResults(50)
.list();
一个命名查询可能会返回一个标量值.你必须使用<return-scalar>元素来指定字段的别名和 Hibernate类型
<sql-query name="mySqlQuery">
<return-scalar column="name" type="string"/>
<return-scalar column="age" type="long"/>
SELECT p.NAME AS name,
p.AGE AS age,
FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
</sql-query>
<return-join>和<load-collection>元素分别用作 外连接和定义那些初始化集合的查询
17.3.1. 使用return-property来明确地指定字段/别名
使用<return-property>你可以明确的告诉Hibernate使用哪些字段,这和使用{}-语法 来让Hibernate注入它自己的别名是相反的.
<sql-query name="mySqlQuery">
<return alias="person" class="eg.Person">
<return-property name="name" column="myName"/>
<return-property name="age" column="myAge"/>
<return-property name="sex" column="mySex"/>
</return>
SELECT person.NAME AS myName,
person.AGE AS myAge,
person.SEX AS mySex,
FROM PERSON person WHERE person.NAME LIKE :name
</sql-query>
<return-property>也可用于多个字段,它解决了使用{}-语法不能细粒度控制多个字段的限制
<sql-query name="organizationCurrentEmployments">
<return alias="emp" class="Employment">
<return-property name="salary">
<return-column name="VALUE"/>
<return-column name="CURRENCY"/>
</return-property>
<return-property name="endDate" column="myEndDate"/>
</return>
SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
FROM EMPLOYMENT
WHERE EMPLOYER = :id AND ENDDATE IS NULL
ORDER BY STARTDATE ASC
</sql-query>
注意在这个例子中,我们使用了<return-property>结合{}的注入语法. 允许用户来选择如何引用字段以及属性.
如果你映射一个识别器(discriminator),你必须使用<return-discriminator>来指定识别器字段
17.3.2. 使用存储过程来查询
Hibernate 3引入了对存储过程查询的支持. 存储过程必须返回一个结果集,作为Hibernate能够使用的第一个外部参数. 下面是一个Oracle9和更高版本的存储过程例子.
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;
在Hibernate里要要使用这个查询,你需要通过命名查询来映射它.
<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>
注意存储过程当前仅仅返回标量和实体.现在不支持<return-join>和<load-collection>
17.3.2.1. 使用存储过程的规则和限制
为了在Hibernate中使用存储过程,你必须遵循一些规则.不遵循这些规则的存储过程将不可用.如果你仍然想要使用他们, 你必须通过session.connection()来执行他们.这些规则针对于不同的数据库.因为数据库 提供商有各种不同的存储过程语法和语义.
对存储过程进行的查询无法使用setFirstResult()/setMaxResults()进行分页。
对于Oracle有如下规则:
存储过程必须返回一个结果集.它通过返回SYS_REFCURSOR实现(在Oracle9或10),在Oracle里你需要定义一个REF CURSOR 类型
推荐的格式是 { ? = call procName(<parameters>) } 或 { ? = call procName }(这更像是Oracle规则而不是Hibernate规则)
对于Sybase或者MS SQL server有如下规则:
存储过程必须返回一个结果集。.注意这些servers可能返回多个结果集以及更新的数目.Hibernate将取出第一条结果集作为它的返回值, 其他将被丢弃。
如果你能够在存储过程里设定SET NOCOUNT ON,这可能会效率更高,但这不是必需的。
17.4. 定制SQL用来create,update和delete
Hibernate3能够使用定制的SQL语句来执行create,update和delete操作。在Hibernate中,持久化的类和集合已经 包含了一套配置期产生的语句(insertsql, deletesql, updatesql等等),这些映射标记 <sql-insert>, <sql-delete>, and <sql-update>重载了 这些语句。
<class name="Person">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ? )</sql-insert>
<sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
<sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
</class>
这些SQL直接在你的数据库里执行,所以你可以自由的使用你喜欢的任意语法。但如果你使用数据库特定的语法, 这当然会降低你映射的可移植性。
如果设定callable,则能够支持存储过程了。
<class name="Person">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<sql-insert callable="true">{call createPerson (?, ?)}</sql-insert>
<sql-delete callable="true">{? = call deletePerson (?)}</sql-delete>
<sql-update callable="true">{? = call updatePerson (?, ?)}</sql-update>
</class>
参数的位置顺序是非常重要的,他们必须和Hibernate所期待的顺序相同。
你能够通过设定日志调试级别为org.hiberante.persister.entity,来查看Hibernate所期待的顺序。在这个级别下, Hibernate将会打印出create,update和delete实体的静态SQL。如果想看到预想中的顺序。记得不要将定制SQL包含在映射文件里, 因为他们会重载Hibernate生成的静态SQL。
在大多数情况下(最好这么做),存储过程需要返回插入/更新/删除的行数,因为Hibernate对语句的成功执行有些运行时的检查。 Hibernate常会把进行CUD操作的语句的第一个参数注册为一个数值型输出参数。
CREATE OR REPLACE FUNCTION updatePerson (uid IN NUMBER, uname IN VARCHAR2)
RETURN NUMBER IS
BEGIN
update PERSON
set
NAME = uname,
where
ID = uid;
return SQL%ROWCOUNT;
END updatePerson;
17.5. 定制装载SQL
你可能需要声明你自己的SQL(或HQL)来装载实体
<sql-query name="person">
<return alias="p" class="Person" lock-mode="upgrade"/>
SELECT NAME AS {p.name}, ID AS {p.id} FROM PERSON WHERE ID=? FOR UPDATE
</sql-query>
这只是一个前面讨论过的命名查询声明,你可以在类映射里引用这个命名查询。
<class name="Person">
<id name="id">
<generator class="increment"/>
</id>
<property name="name" not-null="true"/>
<loader query-ref="person"/>
</class>
这也可以用于存储过程
TODO: 未完成的例子
<sql-query name="organizationEmployments">
<load-collection alias="empcol" role="Organization.employments"/>
SELECT {empcol.*}
FROM EMPLOYMENT empcol
WHERE EMPLOYER = :id
ORDER BY STARTDATE ASC, EMPLOYEE ASC
</sql-query>
<sql-query name="organizationCurrentEmployments">
<return alias="emp" class="Employment"/>
<synchronize table="EMPLOYMENT"/>
SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
REGIONCODE as {emp.regionCode}, ID AS {emp.id}
FROM EMPLOYMENT
WHERE EMPLOYER = :id AND ENDDATE IS NULL
ORDER BY STARTDATE ASC
</sql-query>
分享到:
相关推荐
然而,尽管Hibernate提供了强大的HQL(Hibernate Query Language)和Criteria API,但在处理某些特定的、复杂的SQL查询时,可能无法满足需求,这时就需要用到“原生的Native SQL查询”。 Native SQL查询允许我们...
Native SQL 查询 (使用 SQLQuery) 在 Hibernate 中,使用 SQLQuery 可以执行 Native SQL 查询,控制查询的执行是通过 SQLQuery 接口进行的,通过执行 Session.createSQLQuery() 获取这个接口。下面将详细介绍如何...
本节主要探讨的是如何在Hibernate框架中使用Native SQL查询,它允许开发者直接执行原生的SQL语句,绕过HQL(Hibernate Query Language)进行更灵活的数据操作。 Hibernate是一个流行的Java对象关系映射(ORM)框架...
本篇文章将深入探讨在Hibernate3中如何通过Native SQL查询部分字段,并将其映射到具体的Java对象上。这种方式在处理一些特定的、效率较高的SQL查询时非常有用。 首先,我们需要理解Hibernate中的`SQLQuery`接口,这...
Microsoft SQL Server Native Client (SQL Native Client) 是一个同时包含 SQL OLE DB 访问接口和 SQL ODBC 驱动程序的动态链接库 (DLL)。它对使用本机代码 API(ODBC、OLE DB 和 ADO)连接到 Microsoft SQL Server ...
SQL Server Native Client 10.0 是微软推出的一款专门用于与SQL Server 2008及后续版本交互的客户端库,它集成了ODBC(Open Database Connectivity)和OLE DB(Object Linking and Embedding, Database)接口。...
开发者可以通过ODBC的API调用来执行SQL查询、事务处理、游标操作等。 **OLE DB**: OLE DB是微软的另一种数据库访问技术,它比ODBC更底层,提供了更多的数据库访问功能。SQL Server Native Client 10.0 的OLE DB...
在SQL Server 2012中,虽然主要推荐使用SQL Server Native Client 11.0,但为了兼容旧版本的SQL Server,如SQL Server 2000,仍然需要使用SQL Server Native Client 10.0。 **1. ODBC与OLE DB接口** - **ODBC**: ...
SQL Server 2008 Native Client是微软推出的一款用于与SQL Server进行数据交互的客户端库,它是SQL Server数据库引擎和应用程序之间的一个接口。这个库包含了ODBC(Open Database Connectivity)驱动程序和OLE DB...
Microsoft SQL Server 2008 Native Client (SQL Server Native Client) 是单一动态链接库 (DLL),其中包含 SQL OLE DB 提供者和 SQL ODBC 驱动程序。此链接库针对使用机器码 API (ODBC、OLE DB 和 ADO) 的应用程序...
SQL Server Native Client 10.0 是微软针对SQL Server数据库管理系统推出的一款客户端接口,主要用于在Windows平台上连接和操作SQL Server 2008及其R2版本。这个压缩包"SQL Server Native Client 10.0.zip"包含了...
SQL Server Native Client 11(简称sqlncli_11)是Microsoft开发的一款用于与SQL Server交互的客户端库,尤其适用于需要高性能数据访问的应用程序。它整合了ODBC(Open Database Connectivity)和OLE DB(Object ...
通过ODBC驱动程序,开发者可以利用SQL Server的功能,如执行SQL查询、事务处理和游标操作。 2. **OLE DB支持**: OLE DB是另一种用于访问数据库的接口,它更接近底层,提供了更高级别的性能和灵活性。SQL Server ...
SQL Server Native Client(简称SQLNCLI)是微软推出的一个专门用于与SQL Server交互的客户端库,它是SQL Server 2005引入的新特性,旨在提供更高效、更安全的数据库访问方式。SQLNCLI集成了ODBC(Open Database ...
- **高性能**:相比早期的数据库访问技术,SQL Server Native Client优化了性能,减少了网络传输,提升了查询速度。 - **高级数据类型支持**:支持SQL Server特有的数据类型,如XML、大型对象(LOB)等。 - **...
Microsoft sql server 2008 Native Client (SQL Server Native Client) 是一个同时包含 SQL OLE DB 访问接口和 SQL ODBC 驱动程序的动态链接库 (DLL)。它对使用本机代码 API(ODBC、OLE DB 和 ADO)连接 Microsoft ...
**Microsoft SQL Server 2005 Native Client** 是一个专门设计用于与Microsoft SQL Server进行高效交互的数据访问组件。它是SQL Server 2005引入的一个重要特性,为开发者提供了更强大的功能和性能优化,同时也兼容...
SQL Server Native Client是微软开发的一款专门用于与SQL Server交互的客户端库,支持多种数据库访问接口,包括ODBC(Open Database Connectivity)和OLE DB(Object Linking and Embedding, Database)。...
在SQL Server Native Client中,ODBC驱动程序提供了用于执行SQL查询、事务处理等功能的接口。 - **OLE DB**:是微软特定的数据库访问技术,它允许开发者直接访问数据库对象,如表、视图和存储过程,提供更底层的...