﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-ximinjie-文章分类-Hibernate</title><link>http://www.blogjava.net/ximinjie/category/46337.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 29 Sep 2010 01:17:34 GMT</lastBuildDate><pubDate>Wed, 29 Sep 2010 01:17:34 GMT</pubDate><ttl>60</ttl><item><title>hibernate hql 大全</title><link>http://www.blogjava.net/ximinjie/articles/332021.html</link><dc:creator>习敏杰</dc:creator><author>习敏杰</author><pubDate>Tue, 14 Sep 2010 14:40:00 GMT</pubDate><guid>http://www.blogjava.net/ximinjie/articles/332021.html</guid><wfw:comment>http://www.blogjava.net/ximinjie/comments/332021.html</wfw:comment><comments>http://www.blogjava.net/ximinjie/articles/332021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ximinjie/comments/commentRss/332021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ximinjie/services/trackbacks/332021.html</trackback:ping><description><![CDATA[<tr>
    <td width="100%" align="center">
    <h2><strong>HQL: Hibernate查询语言</strong></h2>
    </td>
</tr>
<tr>
    <td width="100%">
    <p>Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构
    上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询，它可以理解如继承、多态 和关联之类的概念。 </p>
    <p>
    </p>
    <div class="titlepage">
    <div>
    <div>
    <h2 class="title"><a name="queryhql" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>第&nbsp;15&nbsp;章&nbsp;HQL: Hibernate查询语言</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构
    上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询，它可以理解如继承、多态 和关联之类的概念。 </p>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-casesensitivity" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.1.&nbsp;大小写敏感性问题</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>除了Java类与属性的名称外，查询语句对大小写并不敏感。 所以 <tt class="literal"><font face="新宋体">SeLeCT</font></tt> 与 <tt class="literal"><font face="新宋体">sELEct</font></tt> 以及 <tt class="literal"><font face="新宋体">SELECT</font></tt> 是相同的，但是 <tt class="literal"><font face="新宋体">org.hibernate.eg.FOO</font></tt> 并不等价于 <tt class="literal"><font face="新宋体">org.hibernate.eg.Foo</font></tt> 并且 <tt class="literal"><font face="新宋体">foo.barSet</font></tt> 也不等价于 <tt class="literal"><font face="新宋体">foo.BARSET</font></tt>。 </p>
    <p>本手册中的HQL关键字将使用小写字母. 很多用户发现使用完全大写的关键字会使查询语句 的可读性更强,
    但我们发现，当把查询语句嵌入到Java语句中的时候使用大写关键字比较难看。 </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-from" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.2.&nbsp;from子句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>Hibernate中最简单的查询语句的形式如下： </p>
    <pre class="programlisting">from eg.Cat</pre>
    <p>该子句简单的返回<tt class="literal"><font face="新宋体">eg.Cat</font></tt>类的所有实例。
    通常我们不需要使用类的全限定名, 因为 <tt class="literal"><font face="新宋体">auto-import</font></tt>（自动引入） 是缺省的情况。 所以我们几乎只使用如下的简单写法： </p>
    <pre class="programlisting">from Cat</pre>
    <p>大多数情况下, 你需要指定一个<span class="emphasis"><em>别名</em></span>, 原因是你可能需要
    在查询语句的其它部分引用到<tt class="literal"><font face="新宋体">Cat</font></tt> </p>
    <pre class="programlisting">from Cat as cat</pre>
    <p>这个语句把别名<tt class="literal"><font face="新宋体">cat</font></tt>指定给类<tt class="literal"><font face="新宋体">Cat</font></tt> 的实例, 这样我们就可以在随后的查询中使用此别名了。 关键字<tt class="literal"><font face="新宋体">as</font></tt> 是可选的，我们也可以这样写: </p>
    <pre class="programlisting">from Cat cat</pre>
    <p>子句中可以同时出现多个类, 其查询结果是产生一个笛卡儿积或产生跨表的连接。 </p>
    <pre class="programlisting">from Formula, Parameter</pre>
    <pre class="programlisting">from Formula as form, Parameter as param</pre>
    <p>查询语句中别名的开头部分小写被认为是实践中的好习惯， 这样做与Java变量的命名标准保持了一致 (比如，<tt class="literal"><font face="新宋体">domesticCat</font></tt>)。 </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-joins" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.3.&nbsp;关联(Association)与连接(Join)</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>我们也可以为相关联的实体甚至是对一个集合中的全部元素指定一个别名, 这时要使用关键字<tt class="literal"><font face="新宋体">join</font></tt>。 </p>
    <pre class="programlisting">from Cat as cat
    inner join cat.mate as mate
    left outer join cat.kittens as kitten</pre>
    <pre class="programlisting">from Cat as cat left join cat.mate.kittens as kittens</pre>
    <pre class="programlisting">from Formula form full join form.parameter param</pre>
    <p>受支持的连接类型是从ANSI SQL中借鉴来的。 </p>
    <div class="itemizedlist">
    <ul type="disc" compact="">
        <li>
        <p><tt class="literal"><font face="新宋体">inner join</font></tt>（内连接） </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">left outer join</font></tt>（左外连接） </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">right outer join</font></tt>（右外连接） </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">full join</font></tt> (全连接，并不常用)
        </p>
        </li>
    </ul>
    </div>
    <p>语句<tt class="literal"><font face="新宋体">inner join</font></tt>, <tt class="literal"><font face="新宋体">left outer join</font></tt> 以及 <tt class="literal"><font face="新宋体">right outer join</font></tt> 可以简写。 </p>
    <pre class="programlisting">from Cat as cat
    join cat.mate as mate
    left join cat.kittens as kitten</pre>
    <p>还有，一个"fetch"连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化，这种方法在使用到集合的情况下尤其有用，对于关联和集合来说，它有效的代替了映射文件中的外联接
    与延迟声明（lazy declarations）. 查看 <a title="20.1.&nbsp;
    抓取策略(Fetching strategies)
    " href="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/performance.html#performance-fetching"><font color="#336699">第&nbsp;20.1&nbsp;节 &#8220; 抓取策略(Fetching strategies) &#8221;</font></a> 以获得等多的信息。 </p>
    <pre class="programlisting">from Cat as cat
    inner join fetch cat.mate
    left join fetch cat.kittens</pre>
    <p>一个fetch连接通常不需要被指定别名, 因为相关联的对象不应当被用在 <tt class="literal"><font face="新宋体">where</font></tt> 子句 (或其它任何子句)中。同时，相关联的对象
    并不在查询的结果中直接返回，但可以通过他们的父对象来访问到他们。 </p>
    <p>注意<tt class="literal"><font face="新宋体">fetch</font></tt>构造变量在使用了<tt class="literal"><font face="新宋体">scroll()</font></tt> 或 <tt class="literal"><font face="新宋体">iterate()</font></tt>函数 的查询中是不能使用的。最后注意，使用<tt class="literal"><font face="新宋体">full join fetch</font></tt> 与 <tt class="literal"><font face="新宋体">right
    join fetch</font></tt>是没有意义的。 </p>
    <p>如果你使用属性级别的延迟获取（lazy fetching）（这是通过重新编写字节码实现的），可以使用 <tt class="literal"><font face="新宋体">fetch all properties</font></tt>
    来强制Hibernate立即取得那些原本需要延迟加载的属性（在第一个查询中）。 </p>
    <pre class="programlisting">from Document fetch all properties order by name</pre>
    <pre class="programlisting">from Document doc fetch all properties where lower(doc.name) like '%cats%'</pre>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-select" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.4.&nbsp;select子句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p><tt class="literal"><font face="新宋体">select</font></tt> 子句选择将哪些对象与属性返 回到查询结果集中.
    考虑如下情况: </p>
    <pre class="programlisting">select mate
    from Cat as cat
    inner join cat.mate as mate</pre>
    <p>该语句将选择<tt class="literal"><font face="新宋体">mate</font></tt>s of other <tt class="literal"><font face="新宋体">Cat</font></tt>s。（其他猫的配偶） 实际上,
    你可以更简洁的用以下的查询语句表达相同的含义: </p>
    <pre class="programlisting">select cat.mate from Cat cat</pre>
    <p>查询语句可以返回值为任何类型的属性，包括返回类型为某种组件(Component)的属性: </p>
    <pre class="programlisting">select cat.name from DomesticCat cat
    where cat.name like 'fri%'</pre>
    <pre class="programlisting">select cust.name.firstName from Customer as cust</pre>
    <p>查询语句可以返回多个对象和（或）属性，存放在 <tt class="literal"><font face="新宋体">Object[]</font></tt>队列中, </p>
    <pre class="programlisting">select mother, offspr, mate.name
    from DomesticCat as mother
    inner join mother.mate as mate
    left outer join mother.kittens as offspr</pre>
    <p>或存放在一个<tt class="literal"><font face="新宋体">List</font></tt>对象中, </p>
    <pre class="programlisting">select new list(mother, offspr, mate.name)
    from DomesticCat as mother
    inner join mother.mate as mate
    left outer join mother.kittens as offspr</pre>
    <p>也可能直接返回一个实际的类型安全的Java对象, </p>
    <pre class="programlisting">select new Family(mother, mate, offspr)
    from DomesticCat as mother
    join mother.mate as mate
    left join mother.kittens as offspr</pre>
    <p>假设类<tt class="literal"><font face="新宋体">Family</font></tt>有一个合适的构造函数. </p>
    <p>你可以使用关键字<tt class="literal"><font face="新宋体">as</font></tt>给&#8220;被选择了的表达式&#8221;指派别名: </p>
    <pre class="programlisting">select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
    from Cat cat</pre>
    <p>这种做法在与子句<tt class="literal"><font face="新宋体">select new map</font></tt>一起使用时最有用:
    </p>
    <pre class="programlisting">select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
    from Cat cat</pre>
    <p>该查询返回了一个<tt class="literal"><font face="新宋体">Map</font></tt>的对象，内容是别名与被选择的值组成的名-值映射。 </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-aggregation" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.5.&nbsp;聚集函数</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>HQL查询甚至可以返回作用于属性之上的聚集函数的计算结果: </p>
    <pre class="programlisting">select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
    from Cat cat</pre>
    <p>受支持的聚集函数如下： </p>
    <div class="itemizedlist">
    <ul type="disc" compact="">
        <li>
        <p><tt class="literal"><font face="新宋体">avg(...), sum(...), min(...),
        max(...)</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">count(*)</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">count(...), count(distinct ...),
        count(all...)</font></tt> </p>
        </li>
    </ul>
    </div>
    <p>你可以在选择子句中使用数学操作符、连接以及经过验证的SQL函数： </p>
    <pre class="programlisting">select cat.weight + sum(kitten.weight)
    from Cat cat
    join cat.kittens kitten
    group by cat.id, cat.weight</pre>
    <pre class="programlisting">select firstName||' '||initial||' '||upper(lastName) from Person</pre>
    <p>关键字<tt class="literal"><font face="新宋体">distinct</font></tt>与<tt class="literal"><font face="新宋体">all</font></tt> 也可以使用，它们具有与SQL相同的语义. </p>
    <pre class="programlisting">select distinct cat.name from Cat cat
    select count(distinct cat.name), count(cat) from Cat cat</pre>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-polymorphism" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.6.&nbsp;多态查询</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>一个如下的查询语句: </p>
    <pre class="programlisting">from Cat as cat</pre>
    <p>不仅返回<tt class="literal"><font face="新宋体">Cat</font></tt>类的实例, 也同时返回子类 <tt class="literal"><font face="新宋体">DomesticCat</font></tt>的实例. Hibernate 可以在<tt class="literal"><font face="新宋体">from</font></tt>子句中指定<span class="emphasis"><em>任何</em></span> Java 类或接口. 查询会返回继承了该类的所有持久化子类
    的实例或返回声明了该接口的所有持久化类的实例。下面的查询语句返回所有的被持久化的对象： </p>
    <pre class="programlisting">from java.lang.Object o</pre>
    <p>接口<tt class="literal"><font face="新宋体">Named</font></tt> 可能被各种各样的持久化类声明： </p>
    <pre class="programlisting">from Named n, Named m where n.name = m.name</pre>
    <p>注意，最后的两个查询将需要超过一个的SQL <tt class="literal"><font face="新宋体">SELECT</font></tt>.这表明<tt class="literal"><font face="新宋体">order
    by</font></tt>子句 没有对整个结果集进行正确的排序. (这也说明你不能对这样的查询使用<tt class="literal"><font face="新宋体">Query.scroll()</font></tt>方法.) </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-where" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.7.&nbsp;where子句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p><tt class="literal"><font face="新宋体">where</font></tt>子句允许你将返回的实例列表的范围缩小.
    如果没有指定别名，你可以使用属性名来直接引用属性: </p>
    <pre class="programlisting">from Cat where name='Fritz'</pre>
    <p>如果指派了别名，需要使用完整的属性名: </p>
    <pre class="programlisting">from Cat as cat where cat.name='Fritz'</pre>
    <p>返回名为（属性name等于）'Fritz'的<tt class="literal"><font face="新宋体">Cat</font></tt>类的实例。
    </p>
    <pre class="programlisting">select foo
    from Foo foo, Bar bar
    where foo.startDate = bar.date</pre>
    <p>将返回所有满足下面条件的<tt class="literal"><font face="新宋体">Foo</font></tt>类的实例： 存在如下的<tt class="literal"><font face="新宋体">bar</font></tt>的一个实例，其<tt class="literal"><font face="新宋体">date</font></tt>属性等于 <tt class="literal"><font face="新宋体">Foo</font></tt>的<tt class="literal"><font face="新宋体">startDate</font></tt>属性。 复合路径表达式使得<tt class="literal"><font face="新宋体">where</font></tt>子句非常的强大，考虑如下情况： </p>
    <pre class="programlisting">from Cat cat where cat.mate.name is not null</pre>
    <p>该查询将被翻译成为一个含有表连接（内连接）的SQL查询。如果你打算写像这样的查询语句 </p>
    <pre class="programlisting">from Foo foo
    where foo.bar.baz.customer.address.city is not null</pre>
    <p>在SQL中，你为达此目的将需要进行一个四表连接的查询。 </p>
    <p><tt class="literal"><font face="新宋体">=</font></tt>运算符不仅可以被用来比较属性的值，也可以用来比较实例：
    </p>
    <pre class="programlisting">from Cat cat, Cat rival where cat.mate = rival.mate</pre>
    <pre class="programlisting">select cat, mate
    from Cat cat, Cat mate
    where cat.mate = mate</pre>
    <p>特殊属性（小写）<tt class="literal"><font face="新宋体">id</font></tt>可以用来表示一个对象的唯一的标识符。（你也可以使用该对象的属性名。） </p>
    <pre class="programlisting">from Cat as cat where cat.id = 123
    from Cat as cat where cat.mate.id = 69</pre>
    <p>第二个查询是有效的。此时不需要进行表连接！ </p>
    <p>同样也可以使用复合标识符。比如<tt class="literal"><font face="新宋体">Person</font></tt>类有一个复合标识符，它由<tt class="literal"><font face="新宋体">country</font></tt>属性 与<tt class="literal"><font face="新宋体">medicareNumber</font></tt>属性组成。 </p>
    <pre class="programlisting">from bank.Person person
    where person.id.country = 'AU'
    and person.id.medicareNumber = 123456</pre>
    <pre class="programlisting">from bank.Account account
    where account.owner.id.country = 'AU'
    and account.owner.id.medicareNumber = 123456</pre>
    <p>第二个查询也不需要进行表连接。 </p>
    <p>同样的，特殊属性<tt class="literal"><font face="新宋体">class</font></tt>在进行多态持久化的情况下被用来存取一个实例的鉴别值（discriminator value）。
    一个嵌入到where子句中的Java类的名字将被转换为该类的鉴别值。 </p>
    <pre class="programlisting">from Cat cat where cat.class = DomesticCat</pre>
    <p>你也可以声明一个属性的类型是组件或者复合用户类型（以及由组件构成的组件等等）。永远不要尝试使用以组件类型来结尾的路径表达式（path-expression）
    （与此相反，你应当使用组件的一个属性来结尾）。 举例来说，如果<tt class="literal"><font face="新宋体">store.owner</font></tt>含有一个包含了组件的实体<tt class="literal"><font face="新宋体">address</font></tt> </p>
    <pre class="programlisting">store.owner.address.city    // 正确
    store.owner.address         // 错误!</pre>
    <p>一个&#8220;任意&#8221;类型有两个特殊的属性<tt class="literal"><font face="新宋体">id</font></tt>和<tt class="literal"><font face="新宋体">class</font></tt>, 来允许我们按照下面的方式表达一个连接（<tt class="literal"><font face="新宋体">AuditLog.item</font></tt> 是一个属性，该属性被映射为<tt class="literal"><font face="新宋体">&lt;any&gt;</font></tt>）。 </p>
    <pre class="programlisting">from AuditLog log, Payment payment
    where log.item.class = 'Payment' and log.item.id = payment.id</pre>
    <p>注意，在上面的查询与句中，<tt class="literal"><font face="新宋体">log.item.class</font></tt> 和
    <tt class="literal"><font face="新宋体">payment.class</font></tt> 将涉及到完全不同的数据库中的列。
    </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-expressions" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.8.&nbsp;表达式</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>在<tt class="literal"><font face="新宋体">where</font></tt>子句中允许使用的表达式包括
    大多数你可以在SQL使用的表达式种类: </p>
    <div class="itemizedlist">
    <ul type="disc" compact="">
        <li>
        <p>数学运算符<tt class="literal"><font face="新宋体">+, -, *, /</font></tt> </p>
        </li>
        <li>
        <p>二进制比较运算符<tt class="literal"><font face="新宋体">=, &gt;=, &lt;=, &lt;&gt;, !=,
        like</font></tt> </p>
        </li>
        <li>
        <p>逻辑运算符<tt class="literal"><font face="新宋体">and, or, not</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">in</font></tt>, <tt class="literal"><font face="新宋体">not in</font></tt>, <tt class="literal"><font face="新宋体">between</font></tt>, <tt class="literal"><font face="新宋体">is
        null</font></tt>, <tt class="literal"><font face="新宋体">is not null</font></tt>, <tt class="literal"><font face="新宋体">is empty</font></tt>, <tt class="literal"><font face="新宋体">is not empty</font></tt>, <tt class="literal"><font face="新宋体">member
        of</font></tt> and <tt class="literal"><font face="新宋体">not member of</font></tt>
        </p>
        </li>
        <li>
        <p>"简单的" case, <tt class="literal"><font face="新宋体">case ... when ... then ... else
        ... end</font></tt>,和 "搜索" case, <tt class="literal"><font face="新宋体">case when ...
        then ... else ... end</font></tt> </p>
        </li>
        <li>
        <p>字符串连接符<tt class="literal"><font face="新宋体">...||...</font></tt> or <tt class="literal"><font face="新宋体">concat(...,...)</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">current_date()</font></tt>, <tt class="literal"><font face="新宋体">current_time()</font></tt>, <tt class="literal"><font face="新宋体">current_timestamp()</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">second(...)</font></tt>, <tt class="literal"><font face="新宋体">minute(...)</font></tt>, <tt class="literal"><font face="新宋体">hour(...)</font></tt>, <tt class="literal"><font face="新宋体">day(...)</font></tt>, <tt class="literal"><font face="新宋体">month(...)</font></tt>, <tt class="literal"><font face="新宋体">year(...)</font></tt>, </p>
        </li>
        <li>
        <p>EJB-QL 3.0定义的任何函数或操作：<tt class="literal"><font face="新宋体">substring(), trim(),
        lower(), upper(), length(), locate(), abs(), sqrt(), bit_length()</font></tt>
        </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">coalesce()</font></tt> 和 <tt class="literal"><font face="新宋体">nullif()</font></tt> </p>
        </li>
        <li>
        <p><tt class="literal"><font face="新宋体">cast(... as ...)</font></tt>,
        其第二个参数是某Hibernate类型的名字，以及<tt class="literal"><font face="新宋体">extract(... from
        ...)</font></tt>，只要ANSI <tt class="literal"><font face="新宋体">cast()</font></tt> 和
        <tt class="literal"><font face="新宋体">extract()</font></tt> 被底层数据库支持 </p>
        </li>
        <li>
        <p>任何数据库支持的SQL标量函数，比如<tt class="literal"><font face="新宋体">sign()</font></tt>, <tt class="literal"><font face="新宋体">trunc()</font></tt>, <tt class="literal"><font face="新宋体">rtrim()</font></tt>, <tt class="literal"><font face="新宋体">sin()</font></tt>
        </p>
        </li>
        <li>
        <p>JDBC参数传入 <tt class="literal"><font face="新宋体">?</font></tt> </p>
        </li>
        <li>
        <p>命名参数<tt class="literal"><font face="新宋体">:name</font></tt>, <tt class="literal"><font face="新宋体">:start_date</font></tt>, <tt class="literal"><font face="新宋体">:x1</font></tt> </p>
        </li>
        <li>
        <p>SQL 直接常量 <tt class="literal"><font face="新宋体">'foo'</font></tt>, <tt class="literal"><font face="新宋体">69</font></tt>, <tt class="literal"><font face="新宋体">'1970-01-01 10:00:01.0'</font></tt> </p>
        </li>
        <li>
        <p>Java <tt class="literal"><font face="新宋体">public static final</font></tt> 类型的常量
        <tt class="literal"><font face="新宋体">eg.Color.TABBY</font></tt> </p>
        </li>
    </ul>
    </div>
    <p>关键字<tt class="literal"><font face="新宋体">in</font></tt>与<tt class="literal"><font face="新宋体">between</font></tt>可按如下方法使用: </p>
    <pre class="programlisting">from DomesticCat cat where cat.name between 'A' and 'B'</pre>
    <pre class="programlisting">from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )</pre>
    <p>而且否定的格式也可以如下书写： </p>
    <pre class="programlisting">from DomesticCat cat where cat.name not between 'A' and 'B'</pre>
    <pre class="programlisting">from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )</pre>
    <p>同样, 子句<tt class="literal"><font face="新宋体">is null</font></tt>与<tt class="literal"><font face="新宋体">is not null</font></tt>可以被用来测试空值(null). </p>
    <p>在Hibernate配置文件中声明HQL&#8220;查询替代（query substitutions）&#8221;之后，
    布尔表达式（Booleans）可以在其他表达式中轻松的使用: </p>
    <pre class="programlisting">&lt;property name="hibernate.query.substitutions"&gt;true 1, false 0&lt;/property&gt;</pre>
    <p>系统将该HQL转换为SQL语句时，该设置表明将用字符 <tt class="literal"><font face="新宋体">1</font></tt> 和
    <tt class="literal"><font face="新宋体">0</font></tt> 来 取代关键字<tt class="literal"><font face="新宋体">true</font></tt> 和 <tt class="literal"><font face="新宋体">false</font></tt>:
    </p>
    <pre class="programlisting">from Cat cat where cat.alive = true</pre>
    <p>你可以用特殊属性<tt class="literal"><font face="新宋体">size</font></tt>, 或是特殊函数<tt class="literal"><font face="新宋体">size()</font></tt>测试一个集合的大小。 </p>
    <pre class="programlisting">from Cat cat where cat.kittens.size &gt; 0</pre>
    <pre class="programlisting">from Cat cat where size(cat.kittens) &gt; 0</pre>
    <p>对于索引了（有序）的集合，你可以使用<tt class="literal"><font face="新宋体">minindex</font></tt> 与 <tt class="literal"><font face="新宋体">maxindex</font></tt>函数来引用到最小与最大的索引序数。 同理，你可以使用<tt class="literal"><font face="新宋体">minelement</font></tt> 与 <tt class="literal"><font face="新宋体">maxelement</font></tt>函数来 引用到一个基本数据类型的集合中最小与最大的元素。 </p>
    <pre class="programlisting">from Calendar cal where maxelement(cal.holidays) &gt; current date</pre>
    <pre class="programlisting">from Order order where maxindex(order.items) &gt; 100</pre>
    <pre class="programlisting">from Order order where minelement(order.items) &gt; 10000</pre>
    <p>在传递一个集合的索引集或者是元素集(<tt class="literal"><font face="新宋体">elements</font></tt>与<tt class="literal"><font face="新宋体">indices</font></tt> 函数)
    或者传递一个子查询的结果的时候，可以使用SQL函数<tt class="literal"><font face="新宋体">any, some, all,
    exists, in</font></tt> </p>
    <pre class="programlisting">select mother from Cat as mother, Cat as kit
    where kit in elements(foo.kittens)</pre>
    <pre class="programlisting">select p from NameList list, Person p
    where p.name = some elements(list.names)</pre>
    <pre class="programlisting">from Cat cat where exists elements(cat.kittens)</pre>
    <pre class="programlisting">from Player p where 3 &gt; all elements(p.scores)</pre>
    <pre class="programlisting">from Show show where 'fizard' in indices(show.acts)</pre>
    <p>注意，在Hibernate3种，这些结构变量- <tt class="literal"><font face="新宋体">size</font></tt>,
    <tt class="literal"><font face="新宋体">elements</font></tt>, <tt class="literal"><font face="新宋体">indices</font></tt>, <tt class="literal"><font face="新宋体">minindex</font></tt>, <tt class="literal"><font face="新宋体">maxindex</font></tt>, <tt class="literal"><font face="新宋体">minelement</font></tt>, <tt class="literal"><font face="新宋体">maxelement</font></tt> - 只能在where子句中使用。 </p>
    <p>一个被索引过的（有序的）集合的元素(arrays, lists, maps)可以在其他索引中被引用（只能在where子句中）： </p>
    <pre class="programlisting">from Order order where order.items[0].id = 1234</pre>
    <pre class="programlisting">select person from Person person, Calendar calendar
    where calendar.holidays['national day'] = person.birthDay
    and person.nationality.calendar = calendar</pre>
    <pre class="programlisting">select item from Item item, Order order
    where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11</pre>
    <pre class="programlisting">select item from Item item, Order order
    where order.items[ maxindex(order.items) ] = item and order.id = 11</pre>
    <p>在<tt class="literal"><font face="新宋体">[]</font></tt>中的表达式甚至可以是一个算数表达式。 </p>
    <pre class="programlisting">select item from Item item, Order order
    where order.items[ size(order.items) - 1 ] = item</pre>
    <p>对于一个一对多的关联（one-to-many association）或是值的集合中的元素， HQL也提供内建的<tt class="literal"><font face="新宋体">index()</font></tt>函数， </p>
    <pre class="programlisting">select item, index(item) from Order order
    join order.items item
    where index(item) &lt; 5</pre>
    <p>如果底层数据库支持标量的SQL函数，它们也可以被使用 </p>
    <pre class="programlisting">from DomesticCat cat where upper(cat.name) like 'FRI%'</pre>
    <p>如果你还不能对所有的这些深信不疑，想想下面的查询。如果使用SQL，语句长度会增长多少，可读性会下降多少： </p>
    <pre class="programlisting">select cust
    from Product prod,
    Store store
    inner join store.customers cust
    where prod.name = 'widget'
    and store.location.name in ( 'Melbourne', 'Sydney' )
    and prod = all elements(cust.currentOrder.lineItems)</pre>
    <p><span class="emphasis"><em>提示:</em></span> 会像如下的语句 </p>
    <pre class="programlisting">SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
    FROM customers cust,
    stores store,
    locations loc,
    store_customers sc,
    product prod
    WHERE prod.name = 'widget'
    AND store.loc_id = loc.id
    AND loc.name IN ( 'Melbourne', 'Sydney' )
    AND sc.store_id = store.id
    AND sc.cust_id = cust.id
    AND prod.id = ALL(
    SELECT item.prod_id
    FROM line_items item, orders o
    WHERE item.order_id = o.id
    AND cust.current_order = o.id
    )</pre>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-ordering" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.9.&nbsp;order
    by子句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>查询返回的列表(list)可以按照一个返回的类或组件（components)中的任何属性（property）进行排序： </p>
    <pre class="programlisting">from DomesticCat cat
    order by cat.name asc, cat.weight desc, cat.birthdate</pre>
    <p>可选的<tt class="literal"><font face="新宋体">asc</font></tt>或<tt class="literal"><font face="新宋体">desc</font></tt>关键字指明了按照升序或降序进行排序. </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-grouping" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.10.&nbsp;group
    by子句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>一个返回聚集值(aggregate values)的查询可以按照一个返回的类或组件（components)中的任何属性（property）进行分组：
    </p>
    <pre class="programlisting">select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color</pre>
    <pre class="programlisting">select foo.id, avg(name), max(name)
    from Foo foo join foo.names name
    group by foo.id</pre>
    <p><tt class="literal"><font face="新宋体">having</font></tt>子句在这里也允许使用. </p>
    <pre class="programlisting">select cat.color, sum(cat.weight), count(cat)
    from Cat cat
    group by cat.color
    having cat.color in (eg.Color.TABBY, eg.Color.BLACK)</pre>
    <p>如果底层的数据库支持的话(例如不能在MySQL中使用)，SQL的一般函数与聚集函数也可以出现 在<tt class="literal"><font face="新宋体">having</font></tt>与<tt class="literal"><font face="新宋体">order
    by</font></tt> 子句中。 </p>
    <pre class="programlisting">select cat
    from Cat cat
    join cat.kittens kitten
    group by cat
    having avg(kitten.weight) &gt; 100
    order by count(kitten) asc, sum(kitten.weight) desc</pre>
    <p>注意<tt class="literal"><font face="新宋体">group by</font></tt>子句与 <tt class="literal"><font face="新宋体">order by</font></tt>子句中都不能包含算术表达式（arithmetic
    expressions）. </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-subqueries" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.11.&nbsp;子查询</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>对于支持子查询的数据库，Hibernate支持在查询中使用子查询。一个子查询必须被圆括号包围起来（经常是SQL聚集函数的圆括号）。
    甚至相互关联的子查询（引用到外部查询中的别名的子查询）也是允许的。 </p>
    <pre class="programlisting">from Cat as fatcat
    where fatcat.weight &gt; (
    select avg(cat.weight) from DomesticCat cat
    )</pre>
    <pre class="programlisting">from DomesticCat as cat
    where cat.name = some (
    select name.nickName from Name as name
    )</pre>
    <pre class="programlisting">from Cat as cat
    where not exists (
    from Cat as mate where mate.mate = cat
    )</pre>
    <pre class="programlisting">from DomesticCat as cat
    where cat.name not in (
    select name.nickName from Name as name
    )</pre>
    <p>在select列表中包含一个表达式以上的子查询，你可以使用一个元组构造符（tuple constructors）： </p>
    <pre class="programlisting">from Cat as cat
    where not ( cat.name, cat.color ) in (
    select cat.name, cat.color from DomesticCat cat
    )</pre>
    <p>注意在某些数据库中（不包括Oracle与HSQL），你也可以在其他语境中使用元组构造符， 比如查询用户类型的组件与组合： </p>
    <pre class="programlisting">from Person where name = ('Gavin', 'A', 'King')</pre>
    <p>该查询等价于更复杂的： </p>
    <pre class="programlisting">from Person where name.first = 'Gavin' and name.initial = 'A' and name.last = 'King')</pre>
    <p>有两个很好的理由使你不应当作这样的事情：首先，它不完全适用于各个数据库平台；其次，查询现在依赖于映射文件中属性的顺序。 </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-examples" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.12.&nbsp;HQL示例</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>Hibernate查询可以非常的强大与复杂。实际上，Hibernate的一个主要卖点就是查询语句的威力。这里有一些例子，它们与我在最近的
    一个项目中使用的查询非常相似。注意你能用到的大多数查询比这些要简单的多！ </p>
    <p>下面的查询对于某个特定的客户的所有未支付的账单，在给定给最小总价值的情况下，返回订单的id，条目的数量和总价值，
    返回值按照总价值的结果进行排序。为了决定价格，查询使用了当前目录。作为转换结果的SQL查询，使用了<tt class="literal"><font face="新宋体">ORDER</font></tt>, <tt class="literal"><font face="新宋体">ORDER_LINE</font></tt>, <tt class="literal"><font face="新宋体">PRODUCT</font></tt>, <tt class="literal"><font face="新宋体">CATALOG</font></tt> 和<tt class="literal"><font face="新宋体">PRICE</font></tt>
    库表。 </p>
    <pre class="programlisting">select order.id, sum(price.amount), count(item)
    from Order as order
    join order.lineItems as item
    join item.product as product,
    Catalog as catalog
    join catalog.prices as price
    where order.paid = false
    and order.customer = :customer
    and price.product = product
    and catalog.effectiveDate &lt; sysdate
    and catalog.effectiveDate &gt;= all (
    select cat.effectiveDate
    from Catalog as cat
    where cat.effectiveDate &lt; sysdate
    )
    group by order
    having sum(price.amount) &gt; :minAmount
    order by sum(price.amount) desc</pre>
    <p>这简直是一个怪物！实际上，在现实生活中，我并不热衷于子查询，所以我的查询语句看起来更像这个： </p>
    <pre class="programlisting">select order.id, sum(price.amount), count(item)
    from Order as order
    join order.lineItems as item
    join item.product as product,
    Catalog as catalog
    join catalog.prices as price
    where order.paid = false
    and order.customer = :customer
    and price.product = product
    and catalog = :currentCatalog
    group by order
    having sum(price.amount) &gt; :minAmount
    order by sum(price.amount) desc</pre>
    <p>下面一个查询计算每一种状态下的支付的数目，除去所有处于<tt class="literal"><font face="新宋体">AWAITING_APPROVAL</font></tt>状态的支付，因为在该状态下
    当前的用户作出了状态的最新改变。该查询被转换成含有两个内连接以及一个相关联的子选择的SQL查询，该查询使用了表 <tt class="literal"><font face="新宋体">PAYMENT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT_STATUS</font></tt> 以及 <tt class="literal"><font face="新宋体">PAYMENT_STATUS_CHANGE</font></tt>。 </p>
    <pre class="programlisting">select count(payment), status.name
    from Payment as payment
    join payment.currentStatus as status
    join payment.statusChanges as statusChange
    where payment.status.name &lt;&gt; PaymentStatus.AWAITING_APPROVAL
    or (
    statusChange.timeStamp = (
    select max(change.timeStamp)
    from PaymentStatusChange change
    where change.payment = payment
    )
    and statusChange.user &lt;&gt; :currentUser
    )
    group by status.name, status.sortOrder
    order by status.sortOrder</pre>
    <p>如果我把<tt class="literal"><font face="新宋体">statusChanges</font></tt>实例集映射为一个列表（list）而不是一个集合（set）, 书写查询语句将更加简单.
    </p>
    <pre class="programlisting">select count(payment), status.name
    from Payment as payment
    join payment.currentStatus as status
    where payment.status.name &lt;&gt; PaymentStatus.AWAITING_APPROVAL
    or payment.statusChanges[ maxIndex(payment.statusChanges) ].user &lt;&gt; :currentUser
    group by status.name, status.sortOrder
    order by status.sortOrder</pre>
    <p>下面一个查询使用了MS SQL Server的 <tt class="literal"><font face="新宋体">isNull()</font></tt>函数用以返回当前用户所属组织的组织帐号及组织未支付的账。 它被转换成一个对表<tt class="literal"><font face="新宋体">ACCOUNT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT</font></tt>, <tt class="literal"><font face="新宋体">PAYMENT_STATUS</font></tt>, <tt class="literal"><font face="新宋体">ACCOUNT_TYPE</font></tt>, <tt class="literal"><font face="新宋体">ORGANIZATION</font></tt> 以及 <tt class="literal"><font face="新宋体">ORG_USER</font></tt>进行的三个内连接， 一个外连接和一个子选择的SQL查询。 </p>
    <pre class="programlisting">select account, payment
    from Account as account
    left outer join account.payments as payment
    where :currentUser in elements(account.holder.users)
    and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate</pre>
    <p>对于一些数据库，我们需要弃用（相关的）子选择。 </p>
    <pre class="programlisting">select account, payment
    from Account as account
    join account.holder.users as user
    left outer join account.payments as payment
    where :currentUser = user
    and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
    order by account.type.sortOrder, account.accountNumber, payment.dueDate</pre>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-bulk" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.13.&nbsp;批量的UPDATE
    &amp; DELETE语句</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>HQL现在支持UPDATE与DELETE语句. 查阅 <a title="14.3.&nbsp;大批量更新/删除（Bulk update/delete）" href="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/batch.html#batch-direct"><font color="#336699">第&nbsp;14.3&nbsp;节 &#8220;大批量更新/删除（Bulk update/delete）&#8221;</font></a> 以获得更多信息。
    </p>
    </div>
    <div lang="zh-cn" class="sect1">
    <div class="titlepage">
    <div>
    <div>
    <h2 style="clear: both" class="title"><a name="queryhql-tipstricks" style="width: 20px; height: 20px; text-indent: 20px; background-image: url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif); background-repeat: no-repeat no-repeat; "></a>15.14.&nbsp;小技巧
    &amp; 小窍门</h2>
    </div>
    </div>
    <div></div>
    </div>
    <p>你可以统计查询结果的数目而不必实际的返回他们： </p>
    <pre class="programlisting">( (Integer) session.iterate("select count(*) from ....").next() ).intValue()</pre>
    <p>若想根据一个集合的大小来进行排序，可以使用如下的语句： </p>
    <pre class="programlisting">select usr.id, usr.name
    from User as usr
    left join usr.messages as msg
    group by usr.id, usr.name
    order by count(msg)</pre>
    <p>如果你的数据库支持子选择，你可以在你的查询的where子句中为选择的大小（selection size）指定一个条件: </p>
    <pre class="programlisting">from User usr where size(usr.messages) &gt;= 1</pre>
    <p>如果你的数据库不支持子选择语句，使用下面的查询： </p>
    <pre class="programlisting">select usr.id, usr.name
    from User usr.name
    join usr.messages msg
    group by usr.id, usr.name
    having count(msg) &gt;= 1</pre>
    <p>因为内连接（inner join）的原因，这个解决方案不能返回含有零个信息的<tt class="literal"><font face="新宋体">User</font></tt> 类的实例, 所以这种情况下使用下面的格式将是有帮助的: </p>
    <pre class="programlisting">select usr.id, usr.name
    from User as usr
    left join usr.messages as msg
    group by usr.id, usr.name
    having count(msg) = 0</pre>
    <p>JavaBean的属性可以被绑定到一个命名查询（named query）的参数上： </p>
    <pre class="programlisting">Query q = s.createQuery("from foo Foo as foo where foo.name=:name and foo.size=:size");
    q.setProperties(fooBean); // fooBean包含方法getName()与getSize()
    List foos = q.list();</pre>
    <p>通过将接口<tt class="literal"><font face="新宋体">Query</font></tt>与一个过滤器（filter）一起使用，集合（Collections）是可以分页的： </p>
    <pre class="programlisting">Query q = s.createFilter( collection, "" ); // 一个简单的过滤器
    q.setMaxResults(PAGE_SIZE);
    q.setFirstResult(PAGE_SIZE * pageNumber);
    List page = q.list();</pre>
    <p>通过使用查询过滤器（query filter）可以将集合（Collection）的原素分组或排序: </p>
    <pre class="programlisting">Collection orderedCollection = s.filter( collection, "order by this.amount" );
    Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );</pre>
    <p>不用通过初始化，你就可以知道一个集合（Collection）的大小： </p>
    <pre class="programlisting">( (Integer) session.iterate("select count(*) from ....").next() ).intValue();</pre>
    </div>
    </td>
</tr>
<img src ="http://www.blogjava.net/ximinjie/aggbug/332021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ximinjie/" target="_blank">习敏杰</a> 2010-09-14 22:40 <a href="http://www.blogjava.net/ximinjie/articles/332021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>