ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
# 14.9\. 表达式 在`where`子句中允许使用的表达式包括 大多数你可以在SQL使用的表达式种类: * 数学运算符`+, -, *, /` * 二进制比较运算符`=, &gt;=, &lt;=, &lt;&gt;, !=, like` * 逻辑运算符`and, or, not` * `in`, `not in`, `between`, `is null`, `is not null`, `is empty`, `is not empty`, `member of` and `not member of` * "简单的" case, `case ... when ... then ... else ... end`,和 "搜索" case, `case when ... then ... else ... end` * 字符串连接符`...||...` or `concat(...,...)` * `current_date()`, `current_time()`, `current_timestamp()` * `second(...)`, `minute(...)`, `hour(...)`, `day(...)`, `month(...)`, `year(...)`, * EJB-QL 3.0定义的任何函数或操作:`substring(), trim(), lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(), mod()` * `coalesce()` 和 `nullif()` * `str()` 把数字或者时间值转换为可读的字符串 * `cast(... as ...)`, 其第二个参数是某Hibernate类型的名字,以及`extract(... from ...)`,只要ANSI `cast()` 和 `extract()` 被底层数据库支持 * HQL `index()` 函数,作用于join的有序集合的别名。 * HQL函数,把集合作为参数:`size(), minelement(), maxelement(), minindex(), maxindex()`,还有特别的`elements()` 和`indices`函数,可以与数量词加以限定:`some, all, exists, any, in`。 * 任何数据库支持的SQL标量函数,比如`sign()`, `trunc()`, `rtrim()`, `sin()` * JDBC风格的参数传入 `?` * 命名参数`:name`, `:start_date`, `:x1` * SQL 直接常量 `'foo'`, `69`, `6.66E+2`, `'1970-01-01 10:00:01.0'` * Java `public static final` 类型的常量 `eg.Color.TABBY` 关键字`in`与`between`可按如下方法使用: ``` from DomesticCat cat where cat.name between 'A' and 'B' ``` ``` from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' ) ``` 而且否定的格式也可以如下书写: ``` from DomesticCat cat where cat.name not between 'A' and 'B' ``` ``` from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' ) ``` 同样, 子句`is null`与`is not null`可以被用来测试空值(null). 在Hibernate配置文件中声明HQL“查询替代(query substitutions)”之后, 布尔表达式(Booleans)可以在其他表达式中轻松的使用: ``` <property name="hibernate.query.substitutions">true 1, false 0</property> ``` 系统将该HQL转换为SQL语句时,该设置表明将用字符 `1` 和 `0` 来 取代关键字`true` 和 `false`: ``` from Cat cat where cat.alive = true ``` 你可以用特殊属性`size`, 或是特殊函数`size()`测试一个集合的大小。 ``` from Cat cat where cat.kittens.size > 0 ``` ``` from Cat cat where size(cat.kittens) > 0 ``` 对于索引了(有序)的集合,你可以使用`minindex` 与 `maxindex`函数来引用到最小与最大的索引序数。 同理,你可以使用`minelement` 与 `maxelement`函数来 引用到一个基本数据类型的集合中最小与最大的元素。 ``` from Calendar cal where maxelement(cal.holidays) > current_date ``` ``` from Order order where maxindex(order.items) > 100 ``` ``` from Order order where minelement(order.items) > 10000 ``` 在传递一个集合的索引集或者是元素集(`elements`与`indices` 函数) 或者传递一个子查询的结果的时候,可以使用SQL函数`any, some, all, exists, in` ``` select mother from Cat as mother, Cat as kit where kit in elements(foo.kittens) ``` ``` select p from NameList list, Person p where p.name = some elements(list.names) ``` ``` from Cat cat where exists elements(cat.kittens) ``` ``` from Player p where 3 > all elements(p.scores) ``` ``` from Show show where 'fizard' in indices(show.acts) ``` 注意,在Hibernate3种,这些结构变量- `size`, `elements`, `indices`, `minindex`, `maxindex`, `minelement`, `maxelement` - 只能在where子句中使用。 一个被索引过的(有序的)集合的元素(arrays, lists, maps)可以在其他索引中被引用(只能在where子句中): ``` from Order order where order.items[0].id = 1234 ``` ``` select person from Person person, Calendar calendar where calendar.holidays['national day'] = person.birthDay and person.nationality.calendar = calendar ``` ``` select item from Item item, Order order where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11 ``` ``` select item from Item item, Order order where order.items[ maxindex(order.items) ] = item and order.id = 11 ``` 在`[]`中的表达式甚至可以是一个算数表达式。 ``` select item from Item item, Order order where order.items[ size(order.items) - 1 ] = item ``` 对于一个一对多的关联(one-to-many association)或是值的集合中的元素, HQL也提供内建的`index()`函数, ``` select item, index(item) from Order order join order.items item where index(item) < 5 ``` 如果底层数据库支持标量的SQL函数,它们也可以被使用 ``` from DomesticCat cat where upper(cat.name) like 'FRI%' ``` 如果你还不能对所有的这些深信不疑,想想下面的查询。如果使用SQL,语句长度会增长多少,可读性会下降多少: ``` 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) ``` _提示:_ 会像如下的语句 ``` 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 ) ```