HQL 是非常有意识的被设计为完全面向对象的查询,它可以理解如继承、多态和关联之类的概念,简化了SQL语句的编写,除了类跟属性以外,本身对大小写并不敏感。但嵌入到java代码中,小写可观性更好些。下面介绍些HQL的常见用法:
以下面的User和Role为测试对象:
User类:
1 public class User {
2
3 private int user_id ;
4
5 private String user_name ;
6
7 private String password ;
8
9 private Date add_date;
10
11 private Set<Role> roles = new HashSet<Role>();
12
13 public User(){} ;
14
15 public User(int user_id,String user_name ,String password ,Date add_date){
16
17 this.user_id = user_id ;
18 this.user_name = user_name;
19 this.password = password ;
20 this.add_date = add_date ;
21 }
22 //set和get方法省略
23
24 }
User.hbm.xml:
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
5
6 <hibernate-mapping package="model">
7 <class name="User" table="sy_user">
8 <id name="user_id" column="user_id">
9 <generator class="native"/>
10 </id>
11 <property name="user_name"/>
12 <property name="password"/>
13 <property name="add_date"/>
14 <set name="roles" table="user_role">
15 <key column="user_id" not-null="true"/>
16 <many-to-many class="Role" column="role_id" />
17 </set>
18 </class>
19 </hibernate-mapping>
Role类:
1 public class Role {
2
3 private int role_id ;
4
5 private String role_name ;
6
7 private String DESCRIPE ;
8
9 //get和set方法省略
10 }
Role.hbm.xml:
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
5
6 <hibernate-mapping package="model">
7 <class name="Role" table="sy_role">
8 <id name="role_id" column="role_id">
9 <generator class="native"/>
10 </id>
11 <property name="role_name"/>
12 <property name="DESCRIPE"/>
13 </class>
14 </hibernate-mapping>
- from 子句
1 from User as user //as可以省略 返回User的所有实例
2
3 from User user ,Role role //同时出现多个类,其查询结果是产生一个笛卡儿积或产生跨表的连接
2. join 连接
我们可以为相关联的实体甚至是对一个集合中的全部元素指定一个别名,这时要使用关键字 join
join 分为:join、left join 、right join 、full join
1 /自动用条件on 关联 fetch抓取 把role同时查询出来,但并不会放入结果集中,只是可以通过User可以得到role数据,不会因session关闭抛异常
2 String hql = "select user from User user join fetch user.roles role " +
3 "where user.user_id = :user_id" ;
4 List<User> rolesList = session.createQuery(hql)
5 .setInteger("user_id", user_id)
6 .list();
注意: 使用 iterate()
来调用查询 ,fetch
构造是不能使用的 ,fetch
也不应该与 setMaxResults()
或 setFirstResult()
共用,这是因为这些操作是基于结果集的,而在预先抓取集合类时可能包含重复的数据,也就是说无法预先知道精确的行数.
使用 full join fetch
与 right join fetch
是没有意义的。
如果你使用属性级别的延迟获取(lazy fetching)(这是通过重新编写字节码实现的),可以使用 fetch all properties
来强制 Hibernate 立即取得那些原本需要延迟加载的属性:
1 from Document fetch all properties order by name
HQL 支持两种关联 join 的形式:implicit(隐式)
与 explicit(显式)
。
显式 :就是form 子句中明确给出了 join 关键字。这是建议使用的方式。
隐式: 形式不使用 join 关键字。关联使用"点号"来进行“引用”。如:
1 select user from user where User.roles.role_name like 'ro%' ;
3.select 子句:
select
子句选择将哪些对象与属性返回到查询结果集中 。 如:
1 select role from User user join user.roles role // 只返回用户拥有的role的属性。可以简写:
2 select user.roles from User user
查询语句可以返回多个对象和(或)属性,存放在 Object[]
队列中,查询结果返回Object[]:
select user.user_id ,user.user_name ,user.password ,role
from User user join user.role
也可以存放在list中,查询结果返回List:
select new List(user.user_id ,user.user_name ,user.password ,role )
from User user join user.role
若对象有符合类型的构造方法,也可以存在自定义对象中,查询结果返回User对象:
1 String hql = "select new User(user.user_id , user.user_name ,user.password ,user.add_date) " +
2 "from User user where user.user_id = :user_id" ;
3 User user = (User) session.createQuery(hql)
4 .setInteger("user_id",user_id)
5 .uniqueResult() ;
可以使用关键字 as
给“被选择了的表达式”指派别名:
select count(user.user_id) as count from User user
这种做法在与子句 select new map
一起使用时最有用:
select new map( max(user_id) as max, min(user_id) as min, count(*) as n )
from User user
该查询返回了一个 Map
的对象,内容是别名与被选择的值组成的名-值映射。
4.分组函数:
avg(...), sum(...), min(...), max(...)
count(*)
count(...), count(distinct ...), count(all...) ...为属性
可以在选择子句中使用数学操作符、连接以及经过验证的 SQL 函数:
select '用户名:'||user.user_name from User user
5.多态查询
Hibernate 可以在
from
子句中指定任何 Java 类或接口。查询会返回继承了该类的所有持久化子类的实例或返回声明了该接口的所有持久化类的实例
select user.user_name from User user
这个将会查询出所有继承了User类的对象的user_name属性,实现接口也是一样的。
6.where 子句
from Cat cat where cat.mate.name is not null
该查询将被翻译成为一个含有表连接(内连接)的 SQL 查询
7. 表达式
在
where
子句中允许使用的表达式包括 大多数可以在 SQL 使用的表达式种类:
-
数学运算符
+,-,*,/
-
二进制比较运算符
=, >=, <=, <>, !=, like
-
逻辑运算符
and,or,not
-
括号
( )
,表示分组 -
in
,not in
,between
,is null
,is not null
,is empty
,is not empty
,member of
andnot member of
-
"Simple" case,
case ... when ... then ... else ... end
, and "searched" case,case when ... then ... else ... end
-
字符串连接符
...||...
orconcat(...,...)
-
current_date()
,current_time()
, andcurrent_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 ...)
,只要 ANSIcast()
和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%'
8.order by 子句
查询返回的列表(list)可以按照一个返回的类或组件(components)中的任何属性(property)进行排序:
from DomesticCat cat
order by cat.name asc, cat.weight desc, cat.birthdate
9.group by 子句
一个返回聚集值(aggregate values)的查询可以按照一个返回的类或组件(components)中的任何属性(property)进行分组:
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)
10. 子查询
Hibernate 支持在查询中使用子查询。一个子查询必须被圆括号包围起来
from Cat as cat
where not exists (
from Cat as mate where mate.mate = cat
)
11.Row value 构造函数语法
通常指的是多值(multi-valued)的比较
from Cat as cat
where not ( cat.name, cat.color ) in (
select cat.name, cat.color from DomesticCat cat
)
from Person p where p.name=('John', 'Jingleheimer-Schmidt')
决定是否使用这个语法的一件因素就是:这个查询将依赖于元数据里的组件子属性(sub-properties)的顺序。