Hibernate框架进阶(下篇)之查询
导读
Hibernate进阶篇分为上中下三篇,本文为最后一篇,主要内容是Hibernate框架的查询,主要包括hql语句查询,criteria查询以及查询策略的选择。
知识框架
Hibernate查询 一、查询方式:hql语言、criteria接口和sql语言。 hql语言和criteria都是面向对象的查询方式,但最终都是要转换为sql语言执行的。 1、hql语言 1)简单查询 2)条件查询 3)排序查询 4)分页查询 5)统计查询 6)投影查询 2、criteria 1)简单查询 2)条件查询 3)排序查询 4)分页查询 5)统计查询 6)离线查询 二、查询策略 Hibernate查询策略主要是查询是两方面的选择:1、是否延迟加载sql查询语句;2、选择何种查询:单表、多表还是子查询。 1、类级别查询策略 类级别延迟加载 2、关联级别查询策略(了解)
三、扩展:多表查询
1、交叉连接
2、内连接
3、外连接
一、查询方式
Hibernate支持三种查询方式:HQL(Hibernate Query Language)、Criteria接口和SQL。其中HQL和Criteria都是面向对象的查询,但最终都要装换为sql查询语句才执行。
1、HQL
为了方便说明,假设有表person和对应的实体类Person,且放于包domain下。
1)简单查询
sql语句:select * from person
hql语句:select * from domain.Person
注:select * 可以省略;如果整个项目下只有一个Person类,那么包名domain也可以省略。
2)条件查询
sql语句:select * from person where pid = ?
sql设置占位符:PreparedStatement.setInt(0,pid);
(方式1)
hql语句:select * from domain.Person where pid = ?
hql设置占位符:session.setParameter(0,pid);
(方式2)
hql语句:select * from domain.Person where pid = :myPid
hql设置占位符:session.setParameter("myPid",pid);
3)排序查询
升序
sql语句:select * from person order by age asc
hql语句:select * from domain.Person order by age asc
降序
sql语句:select * from person order by age desc
hql语句:select * from domain.Person order by age desc
4)分页查询
sql语句:select * from person limit ?,?
hql语句:select * from domain.Person limit ?,?
hql分页占位符:session.setFirstResult(first);
session.setMaxResults(max);
注:first代表分页的第一条数据,max代表分页的总条数。
5)统计查询
sql语句:select count(*) from person
hql语句:select count(*) from domain.Person
注:常用的聚合函数包括: count(字段)、 sum(字段)、 avg(字段)、 min(字段)、 max(字段)。
6)投影查询
投影查询其实就是查询需要的字段或字段组合。如只查询person表的age字段
sql语句:select age from person
hql语句:select age from domain.Person
2、Criteria
criteria接口时完全面向对象的查询方式,不再像hql一样还需要书写语句,而是完全地通过调用方法来进行查询操作。
常用对象:
1)Criteria接口
2)查询执行对象Restrictions对象。提供了很多静态方法以供查询使用:
1)简单查询
1 //获得criteria 2 Criteria criteria = session.createCriteria(Person.class); 3 //获得结果集 4 List<Person> list = criteria.list();
2)条件查询
1 //获得criteria 2 Criteria criteria = session.createCriteria(Person.class); 3 4 //添加查询条件 5 SimpleExpression eq = Restrictions.eq("name", "张三"); 6 criteria.add(eq);//查询name="张三"的记录 7 8 //获得结果集 9 List<Person> list = criteria.list();
相关的查询方法看上文的表格。
3)排序查询
1 //获得criteria 2 Criteria criteria = session.createCriteria(Person.class); 3 4 //添加排序条件 5 Order asc = Order.asc("age");//按年龄升序排序 6 criteria.addOrder(asc); 7 8 //获得结果集 9 List<Person> list = criteria.list();
4)分页查询
1 //获得criteria 2 Criteria criteria = session.createCriteria(Person.class); 3 4 //添加分页条件 5 criteria.setFirstResult(0); 6 criteria.setMaxResults(5); 7 8 //获得结果集 9 List<Person> list = criteria.list();
5)统计查询
1 //获得criteria 2 Criteria criteria = session.createCriteria(Person.class); 3 4 //添加统计条件 5 criteria.setProjection(Projections.rowCount());//查询总记录数 6 7 //获得结果 8 Long count = (Long)criteria.uniqueResult();
6)离线查询
我们上面使用的criteria对象是由session创建的,所以要使用criteria对象必须先有session对象。但是DetachedCriteria对象(离线条件查询对象)可以直接创建而不通过session,且也能调用上面的查询语句,唯一不同之处在于DetachedCriteria是没有与session对象绑定的,所以称为离线查询对象。
DetachedCriteria对象的出现主要是运用在java的三层架构上,比如当web层需要传递很多参数作为查询条件时,将参数传到service层再传给dao层是十分麻烦的。我们可以在web直接使用DetachedCriteria离线查询,然后只传递这个对象给dao层即可。
需要注意的两个api:
DetachedCriteria对象的创建:
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Person.class);
DetachedCriteria对象与session绑定:(离线查询绑定之后就能持久化到数据库了)
detachedCriteria.getExecutableCriteria(session);
二、查询策略
Hibernate查询策略主要是查询是两方面的选择:1、是否延迟加载sql查询语句;2、选择何种查询:单表、多表还是子查询。
1、类级别查询策略
类级别查询策略主要是延迟加载策略,延迟加载就是当session从数据库加载对象是先不调用sql查询语句,直到该对象使用时再加载。延迟加载最大化地优化了查询,及不使用就不必执行查询了。
如何使用:1)在配置文件中的class元素中配置属性:lazy=true(false表示不延迟加载)。当然,默认就是true,所以如果使用延迟加载就忽略这个配置。
2)使用upload()方法代替get()方法读取对象。(get方法不支持延迟加载策略)
问题:延迟加载是在对象与session绑定是才生效,所以一旦session.close之后再操作对象就会发生异常。
2、关联级别查询策略
关联级别即多表关系中,在关联属性下的属性配置:
其实关联级别的默认属性就是性能最优状态了,感兴趣的可以手动配置上面的信息进行性能比较。
问题:但是要注意的一个问题就是上面说到的延迟加载问题,一旦session关闭就不能再获取加载的对象了,这个问题主要发生在Java三层架构中,当页面需要获得数据库的某条记录时,我们使用到了延迟加载,而当返回页面时显然session对象已经关闭,这是页面就无法获得该对象(该记录)。如何保证在页面使用到该对象时session处于绑定(未关闭)状态呢?
解决:使用filter过滤器可以扩展session的作用范围:即在filter初始化时就打开session,然后放行,在页面加载结束后再关闭session即可。
三、扩展:多表查询
多表查询分为:交叉连接(笛卡尔积);内连接;外连接。
1、交叉连接
即两个表笛卡尔积组合表,一般我们避免使用。
2、内连接
1)隐示内连接
sql语句:select * from A a,B b where b.aid = a.id
2)显示内连接
sql语句:select * from A a inner join B b on b.aid = a.id
3、外连接
1)左外连接
sql语句:select * from A a left [outer] join B on b.aid=a.id;
2)右外连接
sql语句:select * from A a right [outer] join B on b.aid=a.id;
(这里的outer可以省略)
看图:
HIbernate框架的进阶内容就总结到这里,大吉大利,今晚吃鸡!