zoukankan      html  css  js  c++  java
  • Hibernate HQL 语法大全(下)

    11.子查询

    对于支持子查询的数据库,Hibernate支持在查询中使用子查询。一个子查询必须被圆括号包围起来(经常是SQL聚集函数的圆括号)。甚至相互关联的子查询(引用到外部查询中的别名的子查询)也是允许的。

    from Cat as fatcat where fatcat.weight > ( select avg(cat.weight) from DomesticCat cat )
    from DomesticCat as cat where cat.name = some ( select name.nickName from Name as name )
    from Cat as cat where not exists ( from Cat as mate where mate.mate = cat )
    from DomesticCat as cat where cat.name not in ( select name.nickName from Name as name )

    在select列表中包含一个表达式以上的子查询,你可以使用一个元组构造符(tuple constructors):

    from Cat as cat where not ( cat.name, cat.color ) in ( select cat.name, cat.color from DomesticCat cat )

    注意在某些数据库中(不包括Oracle与HSQL),你也可以在其他语境中使用元组构造符, 比如查询用户类型的组件与组合:

    from Person where name = ('Gavin', 'A', 'King')

    该查询等价于更复杂的:

    from Person where name.first = 'Gavin' and name.initial = 'A' and name.last = 'King')

    有两个很好的理由使你不应当作这样的事情:首先,它不完全适用于各个数据库平台;其次,查询现在依赖于映射文件中属性的顺序。

    12.HQL示例

    Hibernate查询可以非常的强大与复杂。实际上,Hibernate的一个主要卖点就是查询语句的威力。这里有一些例子,它们与我在最近的一个项目中使用的查询非常相似。注意你能用到的大多数查询比这些要简单的多!

    下面的查询对于某个特定的客户的所有未支付的账单,在给定给最小总价值的情况下,返回订单的id,条目的数量和总价值,返回值按照总价值的结果进行排序。为了决定价格,查询使用了当前目录。作为转换结果的SQL查询,使用了ORDERORDER_LINEPRODUCTCATALOG 和PRICE 库表。

    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 < sysdate and catalog.effectiveDate >= all ( select cat.effectiveDate from Catalog as cat where cat.effectiveDate < sysdate ) group by order having sum(price.amount) > :minAmount order by sum(price.amount) desc

    这简直是一个怪物!实际上,在现实生活中,我并不热衷于子查询,所以我的查询语句看起来更像这个:

    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) > :minAmount order by sum(price.amount) desc

    下面一个查询计算每一种状态下的支付的数目,除去所有处于AWAITING_APPROVAL状态的支付,因为在该状态下当前的用户作出了状态的最新改变。该查询被转换成含有两个内连接以及一个相关联的子选择的SQL查询,该查询使用了表 PAYMENTPAYMENT_STATUS 以及 PAYMENT_STATUS_CHANGE

    select count(payment), status.name from Payment as payment join payment.currentStatus as status join payment.statusChanges as statusChange where 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.sortOrder order by status.sortOrder

    如果我把statusChanges实例集映射为一个列表(list)而不是一个集合(set), 书写查询语句将更加简单.

    select count(payment), status.name from Payment as payment join payment.currentStatus as status where payment.status.name <> PaymentStatus.AWAITING_APPROVAL or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <> :currentUser group by status.name, status.sortOrder order by status.sortOrder

    下面一个查询使用了MS SQL Server的 isNull()函数用以返回当前用户所属组织的组织帐号及组织未支付的账。它被转换成一个对表ACCOUNTPAYMENTPAYMENT_STATUSACCOUNT_TYPEORGANIZATION以及 ORG_USER进行的三个内连接,一个外连接和一个子选择的SQL查询。

    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

    对于一些数据库,我们需要弃用(相关的)子选择。

    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

    13.批量的UPDATE & DELETE语句

    HQL现在支持UPDATE与DELETE语句.

    14.小技巧 & 小窍门

    你可以统计查询结果的数目而不必实际的返回他们:

    ( (Integer) session.iterate("select count(*) from ....").next() ).intValue()

    若想根据一个集合的大小来进行排序,可以使用如下的语句:

    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)

    如果你的数据库支持子选择,你可以在你的查询的where子句中为选择的大小(selection size)指定一个条件:

    from User usr where size(usr.messages) >= 1

    如果你的数据库不支持子选择语句,使用下面的查询:

    select usr.id, usr.name from User usr.name join usr.messages msg group by usr.id, usr.name having count(msg) >= 1

    因为内连接(inner join)的原因,这个解决方案不能返回含有零个信息的User 类的实例, 所以这种情况下使用下面的格式将是有帮助的:

    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

    JavaBean的属性可以被绑定到一个命名查询(named query)的参数上:

    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();

    通过将接口Query与一个过滤器(filter)一起使用,集合(Collections)是可以分页的:

    Query q = s.createFilter( collection, "" ); // 一个简单的过滤器 q.setMaxResults(PAGE_SIZE); q.setFirstResult(PAGE_SIZE * pageNumber); List page = q.list();

    通过使用查询过滤器(query filter)可以将集合(Collection)的原素分组或排序:

    Collection orderedCollection = s.filter( collection, "order by this.amount" ); Collection counts = s.filter( collection, "select this.type, count(this) group by this.type" );

    不用通过初始化,你就可以知道一个集合(Collection)的大小:

    ( (Integer) session.iterate("select count(*) from ....").next() ).intValue();
  • 相关阅读:
    SQL Server中生成指定长度的流水号
    属性与字段的区别
    Tomcat启动时的异常~!!!
    全面认识验证身份的数字证书
    MyEclipse 5.5 开发 Spring + Struts + Hibernate 的详解视频(长1.5小时)
    resin是什么?是Application Server吗?是WebLogic,Websphere他们的竞争对手吗?
    发现一个HTML得秘密
    用 MyEclipse 开发的最简单的 Spring 例子
    什么是WebSphere?WebSphere是干什么用的?中间件是什么意思?
    简单jsp+servlet实例
  • 原文地址:https://www.cnblogs.com/muyuge/p/6152670.html
Copyright © 2011-2022 走看看