Hibernate 检索策略

来源:互联网 发布:linux ls 时间排序 编辑:程序博客网 时间:2024/05/06 04:12

Hibernate 检索策略

类级别的检索策略

默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>上配置lazy属性来确定检索策略。对于session的检索策略方式,类级别检索策略仅适用于load方法;也就说,对于get、query检索,持久化对象都会被立即加载而不管lazy是false还是true。一般来说,我们检索对象就是要访问它,因此立即检索时通常的选择。由于load方法在检索对象时会抛出异常(立即检索的情况下),因此并不建议使用load检索;而由于<class>中的lazy还影响到多对一及一对一的检索策略,因此使用load方法就更没有必要了。

关联级别的检索策略

         在映射文件中,用<set>元素来配置一对多关联关系。<set>元素有lazy和fetch属性。

                   Lazy:主要决定orders集合被初始化的时机。即到底是在加载Customer对象是被初始化,还是在访问orders集合时被初始化。

                   Fetch:取值为“select”或“subselect”时,决定初始化orders的查询语句的形式;若取值为“join”,则决定orders集合被初始化的时机。

                   若把fetch设置为“join”,lazy属性将被忽略。

类级别的检索默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>上配置lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true.一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使用load检索;而由于<class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。

关系级别的检索策略主要体现在set集合标签中,对检索策略的影响取决于lazy和fecth属性:

Lazy:主要决定orders集合被初始化的时机,即到底是在加载Customer对象时就被初始化,还是在程序访问orders集合时被初始化

Fetch:取值为select或subselect时,决定初始化orders的查询语句的形式,若取值为join,则决定orders集合被初始化的时机

若把fecth设置为join,lazy属性将被忽略

注:fetch默认值是select,lazy的默认值是true

迫切左外连接检索(优先级最高)
fetch 属性有三种值
1.当用到fetch=join时一定是迫切左外连接检索.
2.当用到fetch=select一定不采用迫切左外连接检索,检索方式与lazy保持一致.
3.当用到fetch=subselect,检索多个Customer时,采用嵌套的子查询订单.

注:fecth和lazy相比,fecth的优先级高

执行的效果为:

假如是根据顾客去查顾客的订单的信息,结果如下:

(1) 没有加fecth时的查询结果

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 customers customers0_ where customers0_.id=?

Hibernate: selectorders0_.cid as cid0_1_, orders0_.id as id1_, orders0_.id as id1_0_,orders0_.number as number1_0_, orders0_.address as address1_0_, orders0_.phoneas phone1_0_, orders0_.odate as odate1_0_, orders0_.sum as sum1_0_,orders0_.status as status1_0_, orders0_.cid as cid1_0_ from orders orders0_where orders0_.cid=?

可见是两条sql查询语句

(2)当fecth=join时,lazy=true时,查询的语句为:

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 customerscustomers0_ left outer join orders orders1_ on customers0_.id=orders1_.cidwhere customers0_.id=?

根据左外连接查询的是一条语句

(3)当fecth=join时,lazy=false时,查询的语句为:

Hibernate: selectcustomers0_.id as id0_1_, customers0_.realName as realName0_1_, customers0_.passas pass0_1_, customers0_.sex as sex0_1_, customers0_.petName as petName0_1_,customers0_.email as email0_1_, customers0_.rdate as rdate0_1_, orders1_.cid ascid0_3_, orders1_.id as id3_, orders1_.id as id1_0_, orders1_.number asnumber1_0_, orders1_.address as address1_0_, orders1_.phone as phone1_0_,orders1_.odate as odate1_0_, orders1_.sum as sum1_0_, orders1_.status asstatus1_0_, orders1_.cid as cid1_0_ from customers customers0_ left outer joinorders orders1_ on customers0_.id=orders1_.cid where customers0_.id=?

(4)当fecth=join时,lazy=Extre时,查询的语句为:

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 customerscustomers0_ left outer join orders orders1_ on customers0_.id=orders1_.cidwhere customers0_.id=?

从以上的三种状态可以看出,当fecth设置为join的时候,不管lazy是什么值,最终的结果都是一样的。

(4) 当fecth=select时,lazy=true时,结果为:立即检索

(5)当fecth=select,lazy=false时,结果为:延迟检索

(6)当fecth=select,lazy=extra时,结果为:延迟检索

(7)当fecth=subselect,lazy也有三种情况,

嵌套子查询(检索多个customer对象时)Lazy属性决定检索策略)

selectcustomer_id,order_number,price from orders where customer_id

in (select id fromcustomers)

 三种检索策略的优缺点

1.立即检索

优点:对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象

缺点:

(1)select()语句多

(2)可能会加载应用程序不需要访问的对象,浪费许多内存空间

优先考虑使用的场合

(1)类级别

(2)应用程序需要立即访问的对象

(3)使用了二级缓存

2.延迟检索

优点:由应用程序决定需要加载哪些对象,可以避免执行多余 的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间

缺点:应用程序如果希望访问游离状态的代理类实例,必须保证它在持久化状态时已经被初始化。

优先考虑使用的场合

(1)一对多或者多对多关联

(2)应用程序不需要立即访问或者根本不会访问的对象

3.迫切左外连接检索

优点:

(1)对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。

(2)使用了外连接,select语句少

缺点:

(1)可能会加载应用程序不需要访问的对象,浪费内存。

(2)复杂的数据库表连接也会影响检索性能。

优先考虑使用的场合

(1)多对一

(2)需要立即访问的对象

(3)数据库有良好的表连接性能。

 

原创粉丝点击