📄 querysql.html
字号:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>第 16 章 Native SQL查询</title><link rel="stylesheet" href="../shared/css/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.65.1"><link rel="home" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="up" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="previous" href="querycriteria.html" title="第 15 章 
 条件查询(Criteria Queries)
 "><link rel="next" href="filters.html" title="第 17 章 过滤数据"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">第 16 章 Native SQL查询</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="querycriteria.html">上一页</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="filters.html">下一页</a></td></tr></table><hr></div><div class="chapter" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title"><a name="querysql"></a>第 16 章 Native SQL查询</h2></div></div><div></div></div><p> 你也可以使用你的数据库的Native SQL语言来查询数据。这对你在要使用数据库的某些特性的时候(比如说在查询提示或者Oracle中的 <tt class="literal">CONNECT</tt>关键字),这是非常有用的。这就能够扫清你把原来直接使用SQL/JDBC 的程序迁移到基于 Hibernate应用的道路上的障碍。 </p><p> Hibernate3允许你使用手写的sql来完成所有的create,update,delete,和load操作(包括存储过程) </p><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="querysql-creating"></a>16.1. 使用<tt class="literal">SQLQuery</tt></h2></div></div><div></div></div><p>对原生SQL查询执行的控制是通过<tt class="literal">SQLQuery</tt>接口进行的,通过执行<tt class="literal">Session.createSQLQuery()</tt>获取这个接口。最简单的情况下,我们可以采用以下形式:</p><pre class="programlisting">List cats = sess.createSQLQuery("select * from cats") .addEntity(Cat.class) .list();</pre><p>这个查询指定了:</p><div class="itemizedlist"><ul type="disc"><li><p>SQL查询字符串</p></li><li><p>查询返回的实体</p></li></ul></div><p>这里,结果集字段名被假设为与映射文件中指明的字段名相同。对于连接了多个表的查询,这就可能造成问题,因为可能在多个表中出现同样名字的字段。下面的方法就可以避免字段名重复的问题:</p><pre class="programlisting">List cats = sess.createSQLQuery("select {cat.*} from cats cat") .addEntity("cat", Cat.class) .list();</pre><p> 这个查询指定了: </p><div class="itemizedlist"><ul type="disc"><li><p> SQL查询语句,它带一个占位符,可以让Hibernate使用字段的别名. </p></li><li><p> 查询返回的实体,和它的SQL表的别名. </p></li></ul></div><p> <tt class="literal">addEntity()</tt>方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。 </p><p> <tt class="literal">addJoin()</tt>方法可以被用于载入其他的实体和集合的关联. </p><pre class="programlisting">List cats = sess.createSQLQuery( "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id" ) .addEntity("cat", Cat.class) .addJoin("kitten", "cat.kittens") .list();</pre><p> 原生的SQL查询可能返回一个简单的标量值或者一个标量和实体的结合体。 </p><pre class="programlisting">Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat") .addScalar("maxWeight", Hibernate.DOUBLE); .uniqueResult();</pre><p>除此之外,你还可以在你的hbm文件中描述结果集映射信息,在查询中使用。</p><pre class="programlisting">List cats = sess.createSQLQuery( "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id" ) .setResultSetMapping("catAndKitten") .list();</pre></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="querysql-aliasreferences"></a>16.2. 别名和属性引用</h2></div></div><div></div></div><p> 上面使用的<tt class="literal">{cat.*}</tt>标记是 "所有属性" 的简写.你可以显式地列出需要的字段,但是你必须让Hibernate 为每一个属性注入字段的别名.这些字段的站位符是以字段别名为前导,再加上属性名.在下面的例子里,我们从一个其他的表(<tt class="literal">cat_log</tt>) 中获取<tt class="literal">Cat</tt>对象,而非Cat对象原本在映射元数据中声明的表.注意我们甚至在where子句中也可以使用属性别名. 对于命名查询,{}语法并不是必需的.你可以在<a href="querysql.html#querysql-namedqueries" title="16.3. 命名SQL查询">第 16.3 节 “命名SQL查询”</a>得到更多的细节. </p><pre class="programlisting">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();</pre><p> <span class="emphasis"><em>注意:</em></span>如果你明确地列出了每个属性,你必须包含<span class="emphasis"><em>这个类</em></span>和<span class="emphasis"><em>它的子类</em></span>的属性! </p><p> 下表列出了使用别名注射参数的不同可能性。注意:下面结果中的别名只是示例,实用时每个别名需要唯一并且不同的名字。 </p><div class="table"><a name="aliasinjection-summary"></a><p class="title"><b>表 16.1. 别名注射(alias injection names)</b></p><table summary="别名注射(alias injection names)" border="1"><colgroup><col><col><col><col></colgroup><thead><tr><th>描述</th><th>语法</th><th>示例</th><td class="auto-generated"> </td></tr></thead><tbody><tr><td>简单属性</td><td><tt class="literal">{[aliasname].[propertyname]</tt></td><td><tt class="literal">A_NAME as {item.name}</tt></td><td class="auto-generated"> </td></tr><tr><td>复合属性</td><td><tt class="literal">{[aliasname].[componentname].[propertyname]}</tt></td><td><tt class="literal">CURRENCY as {item.amount.currency}, VALUE as {item.amount.value}</tt></td><td class="auto-generated"> </td></tr><tr><td>实体辨别器(Discriminator of an entity)</td><td><tt class="literal">{[aliasname].class}</tt></td><td><tt class="literal">DISC as {item.class}</tt></td><td class="auto-generated"> </td></tr><tr><td>实体的所有属性</td><td><tt class="literal">{[aliasname].*}</tt></td><td><tt class="literal">{item.*}</tt></td><td class="auto-generated"> </td></tr><tr><td>集合键(collection key)</td><td><tt class="literal">{[aliasname].key}</tt></td><td><tt class="literal">ORGID as {coll.key}</tt></td><td class="auto-generated"> </td></tr><tr><td>集合id</td><td><tt class="literal">{[aliasname].id}</tt></td><td><tt class="literal">EMPID as {coll.id}</tt></td><td class="auto-generated"> </td></tr><tr><td>集合元素</td><td><tt class="literal">{[aliasname].element}</tt></td><td><tt class="literal">XID as {coll.element}</tt></td><td> </td></tr><tr><td>集合元素的属性</td><td><tt class="literal">{[aliasname].element.[propertyname]}</tt></td><td><tt class="literal">NAME as {coll.element.name}</tt></td><td class="auto-generated"> </td></tr><tr><td>集合元素的所有属性</td><td><tt class="literal">{[aliasname].element.*}</tt></td><td><tt class="literal">{coll.element.*}</tt></td><td class="auto-generated"> </td></tr><tr><td>集合的所有属性</td><td><tt class="literal">{[aliasname].*}</tt></td><td><tt class="literal">{coll.*}</tt></td><td class="auto-generated"> </td></tr></tbody></table></div></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="querysql-namedqueries"></a>16.3. 命名SQL查询</h2></div></div><div></div></div><p> 可以在映射文档中定义查询的名字,然后就可以象调用一个命名的HQL查询一样直接调用命名SQL查询.在这种情况下,我们<span class="emphasis"><em>不</em></span> 需要调用<tt class="literal">addEntity()</tt>方法. </p><pre class="programlisting"><sql-query name="persons"> <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 :namePattern</sql-query></pre><pre class="programlisting">List people = sess.getNamedQuery("persons") .setString("namePattern", namePattern) .setMaxResults(50) .list();</pre><p><tt class="literal"><return-join></tt>和 <tt class="literal"><load-collection></tt> 元素是用来连接关联以及将查询定义为预先初始化各个集合的。</p><pre class="programlisting"><sql-query name="personsWith"> <return alias="person" class="eg.Person"/> <return-join alias="address" property="person.mailingAddress"/> SELECT person.NAME AS {person.name}, person.AGE AS {person.age}, person.SEX AS {person.sex}, adddress.STREET AS {address.street}, adddress.CITY AS {address.city}, adddress.STATE AS {address.state}, adddress.ZIP AS {address.zip} FROM PERSON person JOIN ADDRESS adddress ON person.ID = address.PERSON_ID AND address.TYPE='MAILING' WHERE person.NAME LIKE :namePattern</sql-query></pre><p> 一个命名查询可能会返回一个标量值.你必须使用<tt class="literal"><return-scalar></tt>元素来指定字段的别名和 Hibernate类型 </p><pre class="programlisting"><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></pre><p> 你可以把结果集映射的信息放在外部的<tt class="literal"><resultset></tt>元素中,这样就可以在多个命名查询间,或者通过<tt class="literal">setResultSetMapping()</tt>API来访问。(此处原文即存疑。原文为:You can externalize the resultset mapping informations in a <tt class="literal"><resultset></tt> element to either reuse them accross several named queries or through the <tt class="literal">setResultSetMapping()</tt> API.) </p><pre class="programlisting"><resultset name="personAddress">
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -