默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>上配置 lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true.一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下)
检索策略可以分为:
1、 类级别的检索
(1) Hibernate3之前采用的都是立即检索策略
(2) Hibernate3采用的是延迟检索策略:
(3) public void findById(){
Session session=HibernateUtil.getSession();
Customers cs=(Customers)session.load(Customers.class, 2);
(4) }
(5) 当运行上面几行代码时,控制台窗口中不会发出sql语句,只有在上面的方法中加System.out.println(cs.getEmail());才会输出sql语句。如下:
(6) Hibernate: selectcustomers0_.id as id0_0_, customers0_.realName as realName0_0_,customers0_.pass as pass0_0_, customers0_.sex as sex0_0_, customers0_.petNameas petName0_0_, customers0_.email as email0_0_, customers0_.rdate as rdate0_0_from pros.customers customers0_ where customers0_.id=?
1) 立即检索策略
优点:
对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象
缺点:
1) select语句的数目太多,需要频繁地访问数据库,会影响检索性能。如果需要查询n个Customer对象,那么必须执行n+1次select查询语句。这种检索策略没有利用sql的连接查询功能
2) 在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象白白浪费了许多内存空间
优先考虑使用的场合:
(1)类级别
(2)应用程序需要立即访问的对象
(3)使用了二级缓存
2) 延迟检索策略
a) 优点:
i. 由应用程序决定需要加载哪些对象,可以避免执行多余的select,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。
b) 缺点:
i. 应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。
c) 优先考虑使用的场合:
i. (1)一对多或者多对多关联
ii. (2)应用程序不需要立即访问或者根本不会访问的对象
2、 延迟检索策略
迫切左外连接检索策略
优点:
(1) 对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象
(2) 使用了外连接,select语句少
缺点:
(1) 可能会加载应用程序不需要访问的对象,浪费内存
(2) 复杂的数据库表连接也会影响检索性能
优先考虑使用的场合:
(1) 多对一
(2) 需要立即访问的对象
(3) 数据库有良好的表连接性能
关联级别检索策略,要给它配置属性fetch
在映射文件中,用set元素来配置一对多关联关系,set元素有lazy和fetch属性
1、 lazy:主要决定orders集合被初始化的时机,既到底是在加载customer对象时被初始化还是在程序访问orders集合时被初始化
2、 fetch:取值为select或subselect时,决定初始化orders的查询语句的形式;若取值为join,则决定orders集合属性被初始化的时机
3、 若把fetch设置为join,lazy属性将被忽略
当fetch的值为join时,不管lazy的属性值为什么,采用的策略都是迫切左外联接检索
Hibernate: selectcustomers0_.id as id0_1_, customers0_.realName as realName0_1_,customers0_.pass as pass0_1_, customers0_.sex as sex0_1_, customers0_.petNameas petName0_1_, customers0_.email as email0_1_, customers0_.rdate as rdate0_1_,orders1_.cid as cid0_3_, orders1_.id as id3_, orders1_.id as id1_0_,orders1_.number as number1_0_, orders1_.address as address1_0_, orders1_.phoneas phone1_0_, orders1_.odate as odate1_0_, orders1_.sum as sum1_0_,orders1_.status as status1_0_, orders1_.cid as cid1_0_ from pros.customerscustomers0_ left outer join pros.Orders orders1_ on customers0_.id=orders1_.cidwhere customers0_.id=?
当fetch的值为select时,采用的策略主要根据lazy的取值决定
Lazy=true
Hibernate: selectcustomers0_.id as id0_0_, customers0_.realName as realName0_0_, customers0_.passas pass0_0_, customers0_.sex as sex0_0_, customers0_.petName as petName0_0_,customers0_.email as email0_0_, customers0_.rdate as rdate0_0_ frompros.customers customers0_ where customers0_.id=?
Lazy=false
Hibernate: selectcustomers0_.id as id0_0_, customers0_.realName as realName0_0_,customers0_.pass as pass0_0_, customers0_.sex as sex0_0_, customers0_.petNameas petName0_0_, customers0_.email as email0_0_, customers0_.rdate as rdate0_0_from pros.customers customers0_ where customers0_.id=?
Hibernate: select orders0_.cidas cid0_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.number asnumber1_0_, orders0_.address as address1_0_, orders0_.phone as phone1_0_,orders0_.odate as odate1_0_, orders0_.sum as sum1_0_, orders0_.status as status1_0_,orders0_.cid as cid1_0_ from pros.Orders orders0_ where orders0_.cid=?
Lazy=extra
Hibernate: select customers0_.id as id0_0_,customers0_.realName as realName0_0_, customers0_.pass as pass0_0_,customers0_.sex as sex0_0_, customers0_.petName as petName0_0_,customers0_.email as email0_0_, customers0_.rdate as rdate0_0_ frompros.customers customers0_ where customers0_.id=?
当fetch的值为subselect时,lazy的属性值同样分为false、true和extra三种情况,采用的检索策略为嵌套子查询(检索多个customer对象时)lazy属性决定检索策略