📄 queryhql.html
字号:
</p><p> 下面的查询对于某个特定的客户的所有未支付的账单,在给定给最小总价值的情况下,返回订单的id,条目的数量和总价值, 返回值按照总价值的结果进行排序。为了决定价格,查询使用了当前目录。作为转换结果的SQL查询,使用了<tt class="literal">ORDER</tt>, <tt class="literal">ORDER_LINE</tt>, <tt class="literal">PRODUCT</tt>, <tt class="literal">CATALOG</tt> 和<tt class="literal">PRICE</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 pricewhere order.paid = false and order.customer = :customer and price.product = product and catalog.effectiveDate < sysdate and catalog.effectiveDate >= all ( select cat.effectiveDate from Catalog as cat where cat.effectiveDate < sysdate )group by orderhaving sum(price.amount) > :minAmountorder 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 pricewhere order.paid = false and order.customer = :customer and price.product = product and catalog = :currentCataloggroup by orderhaving sum(price.amount) > :minAmountorder by sum(price.amount) desc</pre><p> 下面一个查询计算每一种状态下的支付的数目,除去所有处于<tt class="literal">AWAITING_APPROVAL</tt>状态的支付,因为在该状态下 当前的用户作出了状态的最新改变。该查询被转换成含有两个内连接以及一个相关联的子选择的SQL查询,该查询使用了表 <tt class="literal">PAYMENT</tt>, <tt class="literal">PAYMENT_STATUS</tt> 以及 <tt class="literal">PAYMENT_STATUS_CHANGE</tt>。 </p><pre class="programlisting">select count(payment), status.name from Payment as payment join payment.currentStatus as status join payment.statusChanges as statusChangewhere payment.status.name <> PaymentStatus.AWAITING_APPROVAL or ( statusChange.timeStamp = ( select max(change.timeStamp) from PaymentStatusChange change where change.payment = payment ) and statusChange.user <> :currentUser )group by status.name, status.sortOrderorder by status.sortOrder</pre><p> 如果我把<tt class="literal">statusChanges</tt>实例集映射为一个列表(list)而不是一个集合(set), 书写查询语句将更加简单. </p><pre class="programlisting">select count(payment), status.name from Payment as payment join payment.currentStatus as statuswhere payment.status.name <> PaymentStatus.AWAITING_APPROVAL or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUsergroup by status.name, status.sortOrderorder by status.sortOrder</pre><p> 下面一个查询使用了MS SQL Server的 <tt class="literal">isNull()</tt>函数用以返回当前用户所属组织的组织帐号及组织未支付的账。 它被转换成一个对表<tt class="literal">ACCOUNT</tt>, <tt class="literal">PAYMENT</tt>, <tt class="literal">PAYMENT_STATUS</tt>, <tt class="literal">ACCOUNT_TYPE</tt>, <tt class="literal">ORGANIZATION</tt> 以及 <tt class="literal">ORG_USER</tt>进行的三个内连接, 一个外连接和一个子选择的SQL查询。 </p><pre class="programlisting">select account, paymentfrom Account as account left outer join account.payments as paymentwhere :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, paymentfrom Account as account join account.holder.users as user left outer join account.payments as paymentwhere :currentUser = user and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)order by account.type.sortOrder, account.accountNumber, payment.dueDate</pre></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="queryhql-bulk"></a>15.13. 批量的UPDATE & DELETE语句</h2></div></div><div></div></div><p> HQL现在支持UPDATE与DELETE语句. 查阅 <a href="batch.html#batch-direct" title="14.3. 大批量更新/删除(Bulk update/delete)">第 14.3 节 “大批量更新/删除(Bulk update/delete)”</a> 以获得更多信息。 </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="queryhql-tipstricks"></a>15.14. 小技巧 & 小窍门</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.namefrom User as usr left join usr.messages as msggroup by usr.id, usr.nameorder by count(msg)</pre><p> 如果你的数据库支持子选择,你可以在你的查询的where子句中为选择的大小(selection size)指定一个条件: </p><pre class="programlisting">from User usr where size(usr.messages) >= 1</pre><p> 如果你的数据库不支持子选择语句,使用下面的查询: </p><pre class="programlisting">select usr.id, usr.namefrom User usr.name join usr.messages msggroup by usr.id, usr.namehaving count(msg) >= 1</pre><p> 因为内连接(inner join)的原因,这个解决方案不能返回含有零个信息的<tt class="literal">User</tt> 类的实例, 所以这种情况下使用下面的格式将是有帮助的: </p><pre class="programlisting">select usr.id, usr.namefrom User as usr left join usr.messages as msggroup by usr.id, usr.namehaving 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">Query</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></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="batch.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">上一级</a></td><td width="40%" align="right"> <a accesskey="n" href="querycriteria.html">下一页</a></td></tr><tr><td width="40%" align="left" valign="top">第 14 章 批量处理(Batch processing) </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> 第 16 章 条件查询(Criteria Queries) </td></tr></table></div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -