1、Hibernate检索策略sql
一、Hibernate提供了三种检索策略:当即检索策略、延迟检索策略(懒加载机制)、迫切左外链接检索策略。Hibernate在3.x之前lazy属性默认为false,Session的get()方法、load()方法默认都使用的是当即检索策略。从3.x之后,lazy属性为true,get()方法使用的是当即检索策略,load()方法默认使用的延迟检索策略。数据库
之前默认的当即检索策略存在两大不足:性能
①、select语句的数据太多,须要频繁的访问数据库,会影响检索性能。若是须要检索查询n个Customer对象,那么必须执行n+1次select查询语句。这种检索策略没有利用sql的连接查询功能,例如,以上5条select语句彻底能够经过如下一条select语句完成:select * from customer left outer join Orders on customers.id=orders.customer_id代理
②、在应用逻辑只须要访问Customer对象,而不须要访问Order对象的场合,加载Order对象彻底是多余的操做,这些多余的Order对象白白浪费了许多内存空间。xml
而HIbernate提供的延迟检索策略能避免多余加载应用程序不须要访问的关联对象,迫切左外链接检索策略则充分利用了sql的外链接查询功能,可以减小select语句的数目。对象
二、类级别和关联级别的检索策略继承
检索策略的做用域 | 可选的检索策略 | 默认的检索策略 | 运行时行为受影响的Session的检索方法 |
类级别接口 |
当即检索内存 延迟检索作用域 |
当即检索 | 仅影响load()方法 |
关联级别 | 当即检索 延迟检索 迫切左外链接检索 |
多对一和一对一关联为外链接检索 一对多和多对多关联为当即检索 |
影响Load()、get()和find()方法 |
在类级别中,可选的检索策略包括当即检索和延迟检索策略,可是它仅影响load()方法,在关联级别中,可选的检索策略包括当即检索、延迟检索和迫切左外链接检索。
三种检索策略的运行机制:
检索策略类型 | 类级别 | 关联级别 |
当即检索 | 当即加载检索方法指定的对象 | 当即加载与检索方法指定的对象关联的对象。 |
延迟检索 | 延迟加载检索方法指定的对象 | 延迟加载与检索方法指定的对象关联的对象。 |
迫切左外链接检索 | 不适用 | 经过左外链接加载与检索方法指定的对象关联的对象 |
2、类级别的检索策略:
一、类级别可选的检索策略包括当即检索和延迟检索,默认为当即检索。若是<class>元素的lazy属性为true,表示采用延迟检索。若是lazy属性为false,表示采用当即检索。从Hibernate3.x之后,类级别的lazy默认为true,表示load()方法采用延迟检索策略。当执行Session的load()方法时,Hibernate不会当即执行查询CUSTOMER表的select语句,仅仅返回Customer类的代理类的实例,这个代理类有如下特征:
①、由Hibernate在运行时动态生成,它扩展了Customer类,所以它继承了Customer类的全部属性和方法,但它的实现对于应用程序时透明的。
②、当HIbernate建立Customer代理类实例时,仅仅初始化了它的OID属性,其余属性全为null,所以这个代理类实例占用内存不多。
③、当应用程序第一次访问Customer代理类实例时,例如调用Customer.getName()方法,HIbernate会初始化代理类实例,在初始化过程当中执行select语句,真正从数据库加载 Customer对象的全部数据。但有个例外,那就是当应用程序访问Customer代理类实例的getId()方法,HIbernate不会初始化代理类实例。
Hibernate类的initialize()静态方法用于在Session范围内显式初始化代理类实例,isInitialize()方法用于判断代理类实例是否已经被初始化。
3、一对多和多对多检索策略
在映射文件中,用<set>元素来配置一对多关联及多对多关联关系。<set>元素有lazy和outer-join属性,
lazy属性 | outer-join属性 | 检索策略 |
false | false | 采用当即检索,这是默认的检索策略 |
false | true | 采用迫切左外链接检索策略 |
true | false | 采用延迟检索策略 |
true | true | 毫无心义 |
HIbernate为Set集合也提供了代理类,它扩展了Set接口,但它的实现对应用程序时透明大的。
<set>元素有一个batch-size属性,用于为延迟检索或当即检索策略设定批量检索数量。批量检索可以减小select语句,提升延迟检索检索或当即检索的性能。
当<set .....batch-size=3>时,HIbernate的select语句,会变为:select * from orders where customer_id=1 or customer_id=2 or customer_id=3。必须根据实际状况肯定批量检索数目,合理的批量检索数目应该控制在3到10之间。
outer-join=true属性,设置迫切左外链接检索策略。
4、多对一和一对一关联的检索策略
一、<many-to-one>元素有一个outer-join属性,他有三个可选值:
①、auto:这是默认值,若是Customer.hbm.xml文件的class元素的lazy属性为true,那么对于Order关联的Customer对象采用延迟检索策略。不然采用迫切左外链接检索策略。
②、true。无论Customer.hbm.xml文件的class元素的lazy属性为true仍是false,对于Order关联的Customer对象都采用迫切左外链接检索策略。
③、false:始终不会对于ORder关联的Customer对象采用迫切左外链接检索策略。
对于多对一或一对一关联,应该优先考虑使用外链接检索策略,由于它比当即检索策略使用的select数据少,假如应用程序仅仅但愿访问ORder对象,并不须要当即访问与ORder对象关联的Customer对象,也能够考虑使用延迟检索策略。
在<one-to-one>一对一关联中,若是使用懒加载机制,必须把<one-to-one>元素中的constrained属性设为true,(constrained属性只能用在一对一关联中)。
5、Hibernate对迫切左外链接检索的限制
假如select语句包含多个一对多关联的外链接,会致使一次检索出大批量的数据,从而影响检索性能,所以Hibernate对迫切左外链接作了限制:
①、在一个select语句中只容许包含一个一对多或多对多关联的迫切左外链接。
②、在一个select语句中容许包含多个多对一或一对一关联的迫切左外链接。