﻿<?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-seasun-随笔分类-1.03 hibernate</title><link>http://www.blogjava.net/shiwenfeng/category/42360.html</link><description>在不断模仿、思考、总结中一步一步进步！</description><language>zh-cn</language><lastBuildDate>Sun, 24 Jan 2010 07:54:30 GMT</lastBuildDate><pubDate>Sun, 24 Jan 2010 07:54:30 GMT</pubDate><ttl>60</ttl><item><title>HQL动态查询</title><link>http://www.blogjava.net/shiwenfeng/archive/2010/01/24/310638.html</link><dc:creator>shiwf</dc:creator><author>shiwf</author><pubDate>Sun, 24 Jan 2010 05:55:00 GMT</pubDate><guid>http://www.blogjava.net/shiwenfeng/archive/2010/01/24/310638.html</guid><wfw:comment>http://www.blogjava.net/shiwenfeng/comments/310638.html</wfw:comment><comments>http://www.blogjava.net/shiwenfeng/archive/2010/01/24/310638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shiwenfeng/comments/commentRss/310638.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shiwenfeng/services/trackbacks/310638.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt"><span style="color: red"><span style="font-size: 12pt"><span style="color: red">请查看此blog: </span><a href="http://conkeyn.javaeye.com/category/35770">http://conkeyn.javaeye.com/category/35770</a> </span></span></span><span style="font-size: 10pt"><br />
<br />
</span>
<p><span style="font-size: small"><span style="font-size: 10pt"><span style="font-weight: bold; font-size: 21px; line-height: 31px">HQL: Hibernate查询语言</span> </span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">Hibernate配备了一种非常强大的查询语言，这种语言看上去很像SQL。但是不要被语法结构上的相似所迷惑，HQL是非常有意识的被设计为完全面向对象的查询，它可以理解如继承、多态 和关联之类的概念。</span> </span></p>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-casesensitivity"></a><span style="font-size: 10pt">1.大小写敏感性问题</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">除了Java类与属性的名称外，查询语句对大小写并不敏感。 所以 <tt><span>SeLeCT</span> </tt>与 <tt><span>sELEct</span> </tt>以及 <tt><span>SELECT</span> </tt>是相同的，但是 <tt><span>org.hibernate.eg.FOO</span> </tt>并不等价于 <tt><span>org.hibernate.eg.Foo</span> </tt>并且 <tt><span>foo.barSet</span> </tt>也不等价于 <tt><span>foo.BARSET</span> </tt>。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">本手册中的HQL关键字将使用小写字母. 很多用户发现使用完全大写的关键字会使查询语句 的可读性更强, 但我们发现，当把查询语句嵌入到Java语句中的时候使用大写关键字比较难看。</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-from"></a><span style="font-size: 10pt">2.from子句</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">Hibernate中最简单的查询语句的形式如下：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from eg.Cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">该子句简单的返回<tt><span>eg.Cat</span> </tt>类的所有实例。通常我们不需要使用类的全限定名, 因为 <tt><span>auto-import</span> </tt>（自动引入） 是缺省的情况。所以我们几乎只使用如下的简单写法：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat
</span>
</span></pre>
<p><span style="font-size: small"><span style="font-size: 10pt">大多数情况下, 你需要指定一个<span><em>别名</em> </span>, 原因是你可能需要 在查询语句的其它部分引用到<tt><span>Cat</span> </tt></span></span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">这个语句把别名<tt><span>cat</span> </tt>指定给类<tt><span>Cat</span> </tt>的实例, 这样我们就可以在随后的查询中使用此别名了。关键字<tt><span>as</span> </tt>是可选的，我们也可以这样写:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">子句中可以同时出现多个类, 其查询结果是产生一个笛卡儿积或产生跨表的连接。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Formula, Parameter
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Formula as form, Parameter as param
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">查询语句中别名的开头部分小写被认为是实践中的好习惯， 这样做与Java变量的命名标准保持了一致 (比如，<tt><span>domesticCat</span> </tt>)。</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-joins"></a><span style="font-size: 10pt">3.关联(Association)与连接(Join)</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">我们也可以为相关联的实体甚至是对一个集合中的全部元素指定一个别名, 这时要使用关键字<tt><span>join</span> </tt>。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat
inner join cat.mate as mate
left outer join cat.kittens as kitten
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat left join cat.mate.kittens as kittens
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Formula form full join form.parameter param
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">受支持的连接类型是从ANSI SQL中借鉴来的。</span> </span></p>
<div>
<ul type="disc" compact>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>inner join</span> </tt>（内连接）</span> </span></p>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>left outer join</span> </tt>（左外连接）</span> </span></p>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>right outer join</span> </tt>（右外连接）</span> </span></p>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>full join</span> </tt>(全连接，并不常用)</span> </span></p>
    </li>
</ul>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">语句<tt><span>inner join</span> </tt>, <tt><span>left outer join</span> </tt>以及 <tt><span>right outer join</span> </tt>可以简写。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat
join cat.mate as mate
left join cat.kittens as kitten
</span>
</span></pre>
<p><span style="font-size: small"><span style="font-size: 10pt">还有，一个"fetch"连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化，这种方法在使用到集合的情况下尤其有用，对于关联和集合来说，它有效的代替了映射文件中的外联接与延迟声明（lazy declarations）. 查看 </span><a title="20.1. 抓取策略(Fetching strategies)" href="http://www.hibernate.org/hib_docs/v3/reference/zh-cn/html/performance.html#performance-fetching"><span style="font-size: 10pt"><span style="color: #336699">第20.1节 &#8220; 抓取策略(Fetching strategies) &#8221;</span> </span></a><span style="font-size: 10pt">以获得等多的信息。</span></span><span style="font-size: 10pt"> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat
inner join fetch cat.mate
left join fetch cat.kittens
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">一个fetch连接通常不需要被指定别名, 因为相关联的对象不应当被用在 <tt><span>where</span> </tt>子句 (或其它任何子句)中。同时，相关联的对象并不在查询的结果中直接返回，但可以通过他们的父对象来访问到他们。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">注意<tt><span>fetch</span> </tt>构造变量在使用了<tt><span>scroll()</span> </tt>或 <tt><span>iterate()</span> </tt>函数的查询中是不能使用的。最后注意，使用<tt><span>full join fetch</span> </tt>与 <tt><span>right join fetch</span> </tt>是没有意义的。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">如果你使用属性级别的延迟获取（lazy fetching）（这是通过重新编写字节码实现的），可以使用 <tt><span>fetch all properties</span> </tt></span>来强制Hibernate立即取得那些原本需要延迟加载的属性（在第一个查询中）。</span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Document fetch all properties order by name
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Document doc fetch all properties where lower(doc.name) like '%cats%'
</span>
</span></pre>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-select"></a><span style="font-size: 10pt">4.select子句</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>select</span> </tt>子句选择将哪些对象与属性返回到查询结果集中. 考虑如下情况:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select mate
from Cat as cat
inner join cat.mate as mate
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">该语句将选择<tt><span>mate</span> </tt>s of other <tt><span>Cat</span> </tt>s。（其他猫的配偶） 实际上, 你可以更简洁的用以下的查询语句表达相同的含义:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cat.mate from Cat cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">查询语句可以返回值为任何类型的属性，包括返回类型为某种组件(Component)的属性:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cat.name from DomesticCat cat
where cat.name like 'fri%'
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cust.name.firstName from Customer as cust
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">查询语句可以返回多个对象和（或）属性，存放在 <tt><span>Object[]</span> </tt>队列中,</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select mother, offspr, mate.name
from DomesticCat as mother
inner join mother.mate as mate
left outer join mother.kittens as offspr
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">或存放在一个<tt><span>List</span> </tt>对象中,</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select new list(mother, offspr, mate.name)
from DomesticCat as mother
inner join mother.mate as mate
left outer join mother.kittens as offspr
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">也可能直接返回一个实际的类型安全的Java对象,</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select new Family(mother, mate, offspr)
from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">假设类<tt><span>Family</span> </tt>有一个合适的构造函数.</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">你可以使用关键字<tt><span>as</span> </tt>给&#8220;被选择了的表达式&#8221;指派别名:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
from Cat cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">这种做法在与子句<tt><span>select new map</span> </tt>一起使用时最有用:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select new map( max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n )
from Cat cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">该查询返回了一个<tt><span>Map</span> </tt>的对象，内容是别名与被选择的值组成的名-值映射。</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-aggregation"></a><span style="font-size: 10pt">5.聚集函数</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">HQL查询甚至可以返回作用于属性之上的聚集函数的计算结果:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
from Cat cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">受支持的聚集函数如下：</span> </span></p>
<div>
<ul type="disc" compact>
    <li>
    <p><span style="font-size: small"><tt><span style="font-size: 10pt"><span>avg(...), sum(...), min(...), max(...)</span> </span></tt></span></p>
    <li>
    <p><span style="font-size: small"><tt><span style="font-size: 10pt"><span>count(*)</span> </span></tt></span></p>
    <li>
    <p><span style="font-size: small"><tt><span style="font-size: 10pt"><span>count(...), count(distinct ...), count(all...)</span> </span></tt></span></p>
    </li>
</ul>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">你可以在选择子句中使用数学操作符、连接以及经过验证的SQL函数：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cat.weight + sum(kitten.weight)
from Cat cat
join cat.kittens kitten
group by cat.id, cat.weight
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select firstName||' '||initial||' '||upper(lastName) from Person
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">关键字<tt><span>distinct</span> </tt>与<tt><span>all</span> </tt>也可以使用，它们具有与SQL相同的语义.</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select distinct cat.name from Cat cat
select count(distinct cat.name), count(cat) from Cat cat
</span>
</span></pre>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-polymorphism"></a><span style="font-size: 10pt">6.多态查询</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">一个如下的查询语句:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">不仅返回<tt><span>Cat</span> </tt>类的实例, 也同时返回子类 <tt><span>DomesticCat</span> </tt>的实例. Hibernate 可以在<tt><span>from</span> </tt>子句中指定<span><em>任何</em> </span>Java 类或接口. 查询会返回继承了该类的所有持久化子类的实例或返回声明了该接口的所有持久化类的实例。下面的查询语句返回所有的被持久化的对象：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from java.lang.Object o
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">接口<tt><span>Named</span> </tt>可能被各种各样的持久化类声明：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Named n, Named m where n.name = m.name
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">注意，最后的两个查询将需要超过一个的SQL <tt><span>SELECT</span> </tt>.这表明<tt><span>order by</span> </tt>子句 没有对整个结果集进行正确的排序. (这也说明你不能对这样的查询使用<tt><span>Query.scroll()</span> </tt>方法.)</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-where"></a><span style="font-size: 10pt">7.where子句</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>where</span> </tt>子句允许你将返回的实例列表的范围缩小. 如果没有指定别名，你可以使用属性名来直接引用属性:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat where name='Fritz'
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">如果指派了别名，需要使用完整的属性名:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat where cat.name='Fritz'
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">返回名为（属性name等于）'Fritz'的<tt><span>Cat</span> </tt>类的实例。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select foo
from Foo foo, Bar bar
where foo.startDate = bar.date
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">将返回所有满足下面条件的<tt><span>Foo</span> </tt>类的实例：存在如下的<tt><span>bar</span> </tt>的一个实例，其<tt><span>date</span> </tt>属性等于 <tt><span>Foo</span> </tt>的<tt><span>startDate</span> </tt>属性。 复合路径表达式使得<tt><span>where</span> </tt>子句非常的强大，考虑如下情况：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where cat.mate.name is not null
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">该查询将被翻译成为一个含有表连接（内连接）的SQL查询。如果你打算写像这样的查询语句</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Foo foo
where foo.bar.baz.customer.address.city is not null
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">在SQL中，你为达此目的将需要进行一个四表连接的查询。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>=</span> </tt>运算符不仅可以被用来比较属性的值，也可以用来比较实例：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat, Cat rival where cat.mate = rival.mate
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cat, mate
from Cat cat, Cat mate
where cat.mate = mate
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">特殊属性（小写）<tt><span>id</span> </tt>可以用来表示一个对象的唯一的标识符。（你也可以使用该对象的属性名。）</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat as cat where cat.id = 123
from Cat as cat where cat.mate.id = 69
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">第二个查询是有效的。此时不需要进行表连接！</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">同样也可以使用复合标识符。比如<tt><span>Person</span> </tt>类有一个复合标识符，它由<tt><span>country</span> </tt>属性 与<tt><span>medicareNumber</span> </tt>属性组成。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from bank.Person person
where person.id.country = 'AU'
and person.id.medicareNumber = 123456
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from bank.Account account
where account.owner.id.country = 'AU'
and account.owner.id.medicareNumber = 123456
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">第二个查询也不需要进行表连接。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">同样的，特殊属性<tt><span>class</span> </tt>在进行多态持久化的情况下被用来存取一个实例的鉴别值（discriminator value）。 一个嵌入到where子句中的Java类的名字将被转换为该类的鉴别值。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where cat.class = DomesticCat
</span>
</span></pre>
<p><span style="font-size: small"><span style="font-size: 10pt">你也可以声明一个属性的类型是组件或者复合用户类型（以及由组件构成的组件等等）。永远不要尝试使用以组件类型来结尾的路径表达式（path-expression_r）（与此相反，你应当使用组件的一个属性来结尾）。 举例来说，如果<tt><span>store.owner</span> </tt>含有一个包含了组件的实体<tt><span>address</span> </tt></span></span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">store.owner.address.city    // 正确
store.owner.address         // 错误!
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">一个&#8220;任意&#8221;类型有两个特殊的属性<tt><span>id</span> </tt>和<tt><span>class</span> </tt>, 来允许我们按照下面的方式表达一个连接（<tt><span>AuditLog.item</span> </tt>是一个属性，该属性被映射为<tt><span>&lt;any&gt;</span> </tt>）。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from AuditLog log, Payment payment
where log.item.class = 'Payment' and log.item.id = payment.id
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">注意，在上面的查询与句中，<tt><span>log.item.class</span> </tt>和 <tt><span>payment.class</span> </tt>将涉及到完全不同的数据库中的列。</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-expression_rs"></a><span style="font-size: 10pt">8.表达式</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">在<tt><span>where</span> </tt>子句中允许使用的表达式包括大多数你可以在SQL使用的表达式种类:</span> </span></p>
<div>
<ul type="disc" compact>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">数学运算符<tt><span>+, -, *, /</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">二进制比较运算符<tt><span>=, &gt;=, &lt;=, &lt;&gt;, !=, like</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">逻辑运算符<tt><span>and, or, not</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt"><tt><span>in</span> </tt>, <tt><span>not in</span> </tt>, <tt><span>between</span> </tt>, <tt><span>is null</span> </tt>, <tt><span>is not null</span> </tt>, <tt><span>is empty</span> </tt>, <tt><span>is not empty</span> </tt>, <tt><span>member of</span> </tt>and <tt><span>not member of</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">"简单的" case, <tt><span>case ... when ... then ... else ... end</span> </tt>,和 "搜索" case, <tt><span>case when ... then ... else ... end</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">字符串连接符<tt><span>...||...</span> </tt>or <tt><span>concat(...,...)</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt"><tt><span>current_date()</span> </tt>, <tt><span>current_time()</span> </tt>, <tt><span>current_timestamp()</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>second(...)</span> </tt>, <tt><span>minute(...)</span> </tt>, <tt><span>hour(...)</span> </tt>, <tt><span>day(...)</span> </tt>, <tt><span>month(...)</span> </tt>, <tt><span>year(...)</span> </tt>,</span> </span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">EJB-QL 3.0定义的任何函数或操作：<tt><span>substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length()</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt"><tt><span>coalesce()</span> </tt>和 <tt><span>nullif()</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>cast(... as ...)</span> </tt>, 其第二个参数是某Hibernate类型的名字，以及<tt><span>extract(... from ...)</span> </tt>，只要ANSI <tt><span>cast()</span> </tt>和 <tt><span>extract()</span> </tt>被底层数据库支持</span> </span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">任何数据库支持的SQL标量函数，比如<tt><span>sign()</span> </tt>, <tt><span>trunc()</span> </tt>, <tt><span>rtrim()</span> </tt>, <tt><span>sin()</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">JDBC参数传入 <tt><span>?</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">命名参数<tt><span>:name</span> </tt>, <tt><span>:start_date</span> </tt>, <tt><span>:x1</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">SQL 直接常量 <tt><span>'foo'</span> </tt>, <tt><span>69</span> </tt>, <tt><span>'1970-01-01 10:00:01.0'</span> </tt></span></span></p>
    <li>
    <p><span style="font-size: small"><span style="font-size: 10pt">Java <tt><span>public static final</span> </tt>类型的常量 <tt><span>eg.Color.TABBY</span> </tt></span></span></p>
    </li>
</ul>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">关键字<tt><span>in</span> </tt>与<tt><span>between</span> </tt>可按如下方法使用:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat where cat.name between 'A' and 'B'
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">而且否定的格式也可以如下书写：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat where cat.name not between 'A' and 'B'
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">同样, 子句<tt><span>is null</span> </tt>与<tt><span>is not null</span> </tt>可以被用来测试空值(null).</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">在Hibernate配置文件中声明HQL&#8220;查询替代（query substitutions）&#8221;之后，布尔表达式（Booleans）可以在其他表达式中轻松的使用:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">&lt;property name="hibernate.query.substitutions"&gt;true 1, false 0&lt;/property&gt;
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">系统将该HQL转换为SQL语句时，该设置表明将用字符 <tt><span>1</span> </tt>和 <tt><span>0</span> </tt>来 取代关键字<tt><span>true</span> </tt>和 <tt><span>false</span> </tt>:</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where cat.alive = true
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">你可以用特殊属性<tt><span>size</span> </tt>, 或是特殊函数<tt><span>size()</span> </tt>测试一个集合的大小。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where cat.kittens.size &gt; 0
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where size(cat.kittens) &gt; 0
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">对于索引了（有序）的集合，你可以使用<tt><span>minindex</span> </tt>与 <tt><span>maxindex</span> </tt>函数来引用到最小与最大的索引序数。同理，你可以使用<tt><span>minelement</span> </tt>与 <tt><span>maxelement</span> </tt>函数来引用到一个基本数据类型的集合中最小与最大的元素。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Calendar cal where maxelement(cal.holidays) &gt; current date
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Order order where maxindex(order.items) &gt; 100
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Order order where minelement(order.items) &gt; 10000
</span>
</span></pre>
<p><span style="font-size: small"><span style="font-size: 10pt">在传递一个集合的索引集或者是元素集(<tt><span>elements</span> </tt>与<tt><span>indices</span> </tt>函数) 或者传递一个子查询的结果的时候，可以使用SQL函数<tt><span>any, some, all, exists, in</span> </tt></span></span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select mother from Cat as mother, Cat as kit
where kit in elements(foo.kittens)
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select p from NameList list, Person p
where p.name = some elements(list.names)
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Cat cat where exists elements(cat.kittens)
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Player p where 3 &gt; all elements(p.scores)
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Show show where 'fizard' in indices(show.acts)
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">注意，在Hibernate3种，这些结构变量- <tt><span>size</span> </tt>, <tt><span>elements</span> </tt>, <tt><span>indices</span> </tt>, <tt><span>minindex</span> </tt>, <tt><span>maxindex</span> </tt>, <tt><span>minelement</span> </tt>, <tt><span>maxelement</span> </tt>- 只能在where子句中使用。</span> </span></p>
<p><span style="font-size: 10pt"><span style="font-size: small">一个被索引过的（有序的）集合的元素(arrays, lists, maps)可以在其他索引中被引用（只能在where子句中）：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from Order order where order.items[0].id = 1234
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select person from Person person, Calendar calendar
where calendar.holidays['national day'] = person.birthDay
and person.nationality.calendar = calendar
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select item from Item item, Order order
where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select item from Item item, Order order
where order.items[ maxindex(order.items) ] = item and order.id = 11
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">在<tt><span>[]</span> </tt>中的表达式甚至可以是一个算数表达式。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select item from Item item, Order order
where order.items[ size(order.items) - 1 ] = item
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">对于一个一对多的关联（one-to-many association）或是值的集合中的元素， HQL也提供内建的<tt><span>index()</span> </tt>函数，</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select item, index(item) from Order order
join order.items item
where index(item) &lt; 5
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">如果底层数据库支持标量的SQL函数，它们也可以被使用</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat where upper(cat.name) like 'FRI%'
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">如果你还不能对所有的这些深信不疑，想想下面的查询。如果使用SQL，语句长度会增长多少，可读性会下降多少：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">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)
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small"><span><em>提示:</em> </span>会像如下的语句</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">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
)
</span>
</span></pre>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-ordering"></a><span style="font-size: 10pt">9.order by子句</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">查询返回的列表(list)可以按照一个返回的类或组件（components)中的任何属性（property）进行排序：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">from DomesticCat cat
order by cat.name asc, cat.weight desc, cat.birthdate
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">可选的<tt><span>asc</span> </tt>或<tt><span>desc</span> </tt>关键字指明了按照升序或降序进行排序.</span> </span></p>
</div>
<div lang="zh-cn" xml:lang="zh-cn">
<div>
<div>
<div>
<h2 style="clear: both"><span style="font-size: small"><a name="queryhql-grouping"></a><span style="font-size: 10pt">10.group by子句</span></span><span style="font-size: 10pt"> </span></h2>
</div>
</div>
</div>
<p><span style="font-size: 10pt"><span style="font-size: small">一个返回聚集值(aggregate values)的查询可以按照一个返回的类或组件（components)中的任何属性（property）进行分组：</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">select cat.color, sum(cat.weight), count(cat)
from Cat cat
group by cat.color
</span>
</span></pre>
<pre><span style="font-size: 10pt"><span style="font-size: small">select foo.id, avg(name), max(name)
from Foo foo join foo.names name
group by foo.id
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small"><tt><span>having</span> </tt>子句在这里也允许使用.</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">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)
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">如果底层的数据库支持的话(例如不能在MySQL中使用)，SQL的一般函数与聚集函数也可以出现 在<tt><span>having</span> </tt>与<tt><span>order by</span> </tt>子句中。</span> </span></p>
<pre><span style="font-size: 10pt"><span style="font-size: small">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
</span>
</span></pre>
<p><span style="font-size: 10pt"><span style="font-size: small">注意<tt><span>group by</span> </tt>子句与 <tt><span>order by</span> </tt>子句中都不能包含算术表达式（arithmetic expression_rs）.</span> </span></p>
</div>
<img src ="http://www.blogjava.net/shiwenfeng/aggbug/310638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shiwenfeng/" target="_blank">shiwf</a> 2010-01-24 13:55 <a href="http://www.blogjava.net/shiwenfeng/archive/2010/01/24/310638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>