Hibernate HQL检索

1 什么是HQL
HQL是Hibernate提供的其中一种检索方式,也是Hibernate使用最为广泛的检索方式。
HQL同SQL语言相似,熟悉了SQL语言以后,学习HQL是非常容易的。
Hibernate提供了Query接口,它是Hibernate提供的专门的HQL查询接口。

2 使用别名
Query query = session.createQuery("from Course as c where c.name=:name ");
也可以省略as ,这点同SQL语句使用别名的方式相同。

3 多态查询
执行Query query = session.createQuery("from java.lang.Object ");
后台输出:
Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.clazzid as clazzid1_ from student student0_
Hibernate: select clazz0_.id as id3_, clazz0_.name as name3_ from clazz clazz0_
Hibernate: select course0_.id as id0_, course0_.name as name0_ from course course0_

也就是说它会查询Object的所有的子类,因为我的hibernate.cfg.xml将其中配置的mapping
包括<mapping resource="course.hbm.xml"/>
<mapping resource="student.hbm.xml"/>
<mapping resource="clazz.hbm.xml"/>,所以后台输出了查询student,course和clazz 3个表的语句。
另外对于接口也适用,例如:
Query query = session.createQuery("from java.io.Serializable ");


4 排序
Query query = session.createQuery("from Course order by id desc ");

同SQL语法一致。

5 分页
Query query = session.createQuery("from Course order by id desc ");
query.setFirstResult(0);//从第一个开始取
query.setMaxResults(2);//一共取几个

数据量较大的查询都会采用分页的方式,避免全部取出造成的数据库和网络压力白白增大,并且应用服务器的session也会被撑大。另外一些前台的分页组件也支持多级分页,比如一页显示10个,1次从数据库中取出100个,这样前10页的话就不需要从数据库中再去检索,等翻到第11页的时候,再去数据库中取出100个,这样数据库的交互进一步减少,而应用服务器的session也不会太大,在纯后台分页和纯前台分页之间取得了一种平衡,计算机领域经常能够见到这种折中设计方案。


6 方法链编程风格
从Hibernate的源码中可以看到:
public Query setFirstResult(int firstResult) {
selection.setFirstRow( new Integer(firstResult) );
return this;
}

public Query setParameter(int position, Object val) throws HibernateException {
if (val == null) {
setParameter( position, val, Hibernate.SERIALIZABLE );
}
else {
setParameter( position, val, determineType( position, val ) );
}
return this;
}

Query接口实现类的方法都返回的是this对象,而不是void。
这样对于之前的分页方法,就可以用下面的方式写:

Query query = session.createQuery("from Course order by id desc ").setFirstResult(0).setMaxResults(2);

怎么样,优雅吧,一个优秀的框架,设计上一定是优雅的。架构一词来自于建筑领域,建筑领域讲究美观、坚固、实用,同样在软件领域,一个优秀的架构,也一定是美的。爱美之心人皆有之,这是人的本性,美的东西使人心情愉悦,比如你想象一下苍laoshi,再想象一下凤姐,我去。无论做什么事情,要想成功,一定不能违背人的本性。扯远了。。

7 检索单个对象
Course course1 = (Course)session.createQuery("from Course order by id desc ").setMaxResults(1).uniqueResult();

如果检索出来的结果有多个对象,那么会抛异常。

8 绑定参数
1)拼字符串方式
String name = "语文";
Query query = session.createQuery("from Course where name='"+name+"'order by id desc ");

这种方式有2个缺点:a.可以被SQL注入攻击 b.每次生成的SQL都是动态的,都需要预编译,浪费了一些CPU周期。

2)按参与名字绑定
Query query = session.createQuery("from Course where name=:name order by id desc ");
query.setString("name","语文");

3)按参数位置绑定
Query query = session.createQuery("from Course where name=? order by id desc ");
query.setString(0,"语文");//从0开始


9 映射文件中定义查询语句
<hibernate-mapping>
...
<query name="getCourse">
from Course
</query>
</hibernate-mapping>

Query query = session.getNamedQuery("getCourse");

如果getCourse语句很长的话,可以采用这种方式。


10 其他查询
其他的查询,如between xx and oo ,>等比较运算 ,where 条件,like '%'等均同SQL语句一样,同SQL保持高度的一致性,好的软件一定是高度一致的,外人看来如同一个人写的,通过一致的解决方案解决产品中相似的问题,这样对于用户来说学习成本是最低的,能不能做到这就看架构师的水平了。古代带兵打仗的将军,也是军队的架构师,制定作战的设计策略,临场随机应变,制定各种决策,如果架构师无能,那么一将无能,祸及三军。公司领导制定公司组织机构,也是一种高层的架构,xiaoping同志就是改革开放的总架构师嘛,最高级别的架构师,如果一个公司经常重构,那么这个公司也就快完蛋了,毕竟重构的不是软件结构不是代码,而是活生生的人,这种重构可能会非常伤害员工的工作热情,搞不好会流失一些业务骨干。

11 投影查询
投影查询是指只查询部分属性。
例如:Query query = session.createQuery("select name from Course");

12 聚合函数
HQL中可以使用count avg sum min max 这些聚合函数。
例如:
Query query = session.createQuery("select count(*) from Course");
Long count = (Long)query.uniqueResult();
/*-------------------------------------分隔代码就靠它了-------------------------------------------------*/
Query query = session.createQuery("select max(name),min(name) from Course");
Object[] obj = (Object[])query.uniqueResult();
System.out.println("obj[0]="+obj[0]+"obj[1]="+obj[1]);


13 分组
示例:
Query query = session.createQuery("select name,count(*) from Course group by name");
Iterator it = query.list().iterator();
while(it.hasNext()){
Object[] obj = (Object[])it.next();
System.out.println("obj[0]="+obj[0]+",obj[1]="+obj[1]);
}


14 关联查询
Clazz对象和Student对象是1:N的双向关联关系,类的源码及表结构请参见:http://frank1234.iteye.com/blog/2172205
1)内连接:Query query = session.createQuery("from Clazz a , Student b where a.id= b.clazz");

输出SQL:
Hibernate: select clazz0_.id as id3_0_, student1_.id as id1_1_, clazz0_.name as name3_0_, student1_.name as name1_1_, student1_.clazzid as clazzid1_1_ from clazz clazz0_, student student1_ where clazz0_.id=student1_.clazzid


2)内连接:Query query = session.createQuery("from Clazz a join a.students");

输出SQL:
Hibernate: select clazz0_.id as id3_0_, students1_.id as id1_1_, clazz0_.name as name3_0_, students1_.name as name1_1_, students1_.clazzid as clazzid1_1_ from clazz clazz0_ inner join student students1_ on clazz0_.id=students1_.clazzid

3)外连接:
Query query = session.createQuery("from Clazz a left join a.students");
输出SQL:
Hibernate: select clazz0_.id as id3_0_, students1_.id as id1_1_, clazz0_.name as name3_0_, students1_.name as name1_1_, students1_.clazzid as clazzid1_1_ from clazz clazz0_ left outer join student students1_ on clazz0_.id=students1_.clazzid

Query query = session.createQuery("from Student a left join a.clazz");
输出SQL:
Hibernate: select student0_.id as id1_0_, clazz1_.id as id3_1_, student0_.name as name1_0_, student0_.clazzid as clazzid1_0_, clazz1_.name as name3_1_ from student student0_ left outer join clazz clazz1_ on student0_.clazzid=clazz1_.id

4)返回值处理
代码示例:
Query query = session.createQuery("from Student a left join a.clazz");
Iterator it = query.list().iterator();
while(it.hasNext()){
Object[] obj = (Object[])it.next();
Student student = (Student) obj[0];
System.out.println("student="+student);
Clazz clazz = (Clazz)obj[1];
System.out.println("clazz="+clazz);
}

obj[0]是 关联表的第一个表,obj[1]是关联表的第二个表。
因为Clazz和Student是1:N关系,所以输出的Clazz对象可能是重复的。

至此笔者的Hibernate之旅告一段落了,笔者还未专研到源代码高度,都是Hibernate最基本的一些概念和知识点。但是也深深感受到了Hibernate的魅力,Hibernate的优雅,有时间的时候再深入研究吧。


《精通Hibernate》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值