Hibernate 的检索策略
来源:互联网 发布:用mac给iphone充电 编辑:程序博客网 时间:2024/04/24 22:06
Hibernate提供了三种检索策略:立即检索、延迟检索和迫切左外连接检索。
类级别检索策略是指定主对象进行检索(如Customer);关联级别检索策略是对与主对象关联的对象进行检索(如Order)。
可选的检索策略
默认的检索策略
运行时受影响的检索方法
类级别
立即检索
延迟检索
延迟检索
仅影响Session的load()方法
关联级别
立即检索
延迟检索
迫切左外连接检索
延迟检索
影响Session的load()和get()方法,以及Query API和Criteria API;例外情况是Query API会忽略迫切左外连接检索策略
类级别
关联级别
立即检索
立即加载检索方法指定的对象
立即加载与检索方法指定的对象关联的对象,可以设定批量检索数量
延迟检索
延迟加载检索方法指定的对象
延迟加载与检索方法指定的对象关联的对象,可以设定批量检索数量
迫切左外连接检索
不适用
通过左外连接加载与检索方法指定的对象关联的对象
类级别
一对多关联级别
多对一关联级别
lazy
<class>元素的lazy属性可选值为:true(延迟检索)和false(立即检索),默认值为true
<set>元素的lazy属性可选值为:true(延迟检索)、extra(增强延迟检索)和false(立即检索),默认值为true
<many-to-one>元素的lazy属性可选值为:proxy(延迟检索)、no-proxy(无代理延迟检索)和false(立即检索),默认值为true
fetch
无此属性
<set>元素的fetch属性可选值为:select(select查询语句)、subselect(带子查询的select语句)和join(迫切左外连接检索),默认值为select
<many-to-one>元素的fetch属性可选值为:select(select查询语句)和join(迫切左外连接检索),默认值为select
batch-size
设定批量检索数量,可选值为一个正整数,默认为1。合理取值为3-10,仅适用于关联级别的立即检索与延迟检索,<class>和<set>包含此属性。
1.类级别的检索策略
1.1.立即检索
Customer.hbm.xml:
<class name="mypack.Customer" table="CUSTOMERS" lazy="false">当通过Session的load()方法检索Customer对象时:
Customer customer = (Customer)session.load(Customer.class, new Long(1));Hibernate会立即执行select语句:
select * from CUSTOMERS where ID=1;
1.2.延迟检索
Customer.hbm.xml:
<class name="mypack.Customer" table="CUSTOMERS">或者
<class name="mypack.Customer" table="CUSTOMERS" lazy="true">当执行Session的load()方法时,Hibernate不会执行select语句,仅返回Customer类的代理类的实例。
代理类仅初始化了OID属性,其余属性为null,应用程序第一次访问Customer的代理类实例时(如customer.getXXX()), Hibernate会初始化代理类实例,执行select语句真正从数据库中加载Customer对象的所有数据。
访问代理类实例的getId()方法时,不会触发Hibernate初始化代理类的行为。
若加载的Customer对象在数据库中不存在,Session的load()方法不会抛异常,只有当运行getXXX()方法时才会抛异常。
若在整个Session范围内,应用程序没有访问过Customer对象,那么Customer代理类的实例一直不会被初始化,且Customer代理类的实例只有在当前Session范围内才能被初始化。
Hibernate的initialize()静态方法用于在Session范围内显示初始化代理类实例:
Customer customer = (Customer)session.load(Customer.class, new Long(1));if(!Hibernate.isInitialized(customer) Hibernate.initialize(customer);session.close();customer.getName();这样,当Session关闭后,可正常访问Customer游离对象。
值得注意的是,Session的get()方法及Query的list()方法在Customer类级别总是使用立即检索策略。
2.一对多和多对多关联的检索策略
Customer.hbm.xml中用以下代码配置Customer和Order的一对多关联关系:
<set name="orders" inverse="true"> <key column="CUSTOMER_ID" /> <one-to-many class="mypack.Order" /></set>
2.1.立即检索(lazy属性值为false)
Customer.hbm.xml:
<set name="orders" inverse="true" lazy="false">...</set>当通过Session的get()方法检索Customer对象时:
Customer customer = (Customer)session.get(Customer.class, new Long(1));
Hibernate会立即执行select语句:
select * from CUSTOMERS where ID=1;select * from ORDERS where CUSTOMER_ID=1;
2.2.延迟检索(lazy属性值为true)
Customer.hbm.xml:
<set name="orders" inverse="true">...</set>或者
<set name="orders" inverse="true" lazy="true">...</set>此时运行Session的get()方法检索Customer对象时,只会执行以下select语句:
select * from CUSTOMERS where ID=1;Customer的orders属性引用了一个没有被初始化的集合代理类实例。以下两种情况会初始化该代理类实例:
(1)应用程序第一次访问它,如调用iterator()、size()、isEmpty()或contains()方法:
Set orders = customer.getOrders();Iterator it = orders.iterator();(2)Hibernate的initialize()静态方法初始化
Set orders = customer.getOrders();Hibernate.initialize(orders);
2.3.增强延迟检索(lazy属性值为extra)
Customer.hbm.xml:
<set name="orders" inverse="extra">...</set>与一般延迟检索策略(lazy为true)很相似,区别在于初始化代理类实例的时机不同,应用程序第一次访问orders属性的iterator()方法时,会初始化代理类实例,而当应用程序第一次访问orders属性的size()、isEmpty()或contains()方法时,不会初始化代理类实例,仅通过特定的select语句查询必要的信息,而不会检索所有Order对象。
2.4.批量延迟检索和批量立即检索(使用batch-size属性)
Customer.hbm.xml:
<set name="orders" inverse="true" lazy="true" batch-size=3>...</set>当访问customer1.getOrders().iterator()方法时,会批量初始化三个orders集合代理类实例,Hibernate执行select语句:
select * from ORDERS where CUSTOMER_ID in (1,2,3);此时,访问customer2/customer3.getOrders().iterator()方法时,不需要再初始化orders集合代理类实例,当访问customer4.getOrders().iterator()方法时,会自动再批量初始化三个orders集合代理类实例。
Customer.hbm.xml:
<set name="orders" inverse="true" lazy="false" batch-size=3>...</set>对于以下检索方法:
List customers = session.createQuery("from Customer as c").list();会立即执行以下select语句:
select * from CUSTOMERS;select * from ORDERS where CUSTOMER_ID in (1,2,3);
2.5.用带子查询的select语句整批量初始化orders集合(fetch属性为subselect)
List customers = session.createQuery("from Customer as c").list(); //第一行Iterator customerI = customers.iterator(); //第二行Customer customer = (Customer)customerI.next(); //第三行Iterator orderI = customer.getOrders().iterator(); //第四行(1)
<set name="orders" inverse="true" lazy="false" batch-size=3>...</set>第一行时,会立即执行以下select语句:
select * from CUSTOMERS;select * from ORDERS where CUSTOMER_ID in (1,2,3);(2)
<set name="orders" inverse="true" lazy="false" fetch="subselect">...</set>第一行时,会立即执行以下select语句:
select * from CUSTOMERS;select * from ORDERS where CUSTOMER_ID in (select ID from CUSTOMERS);(3)
<set name="orders" inverse="true" batch-size=3>...</set>第四行时会初始化orders集合代理类实例,执行以下select语句:
select * from ORDERS where CUSTOMER_ID in (1,2,3);(4)
<set name="orders" inverse="true" fetch="subselect">...</set>第四行时会初始化orders集合代理类实例,执行以下select语句:
select * from ORDERS where CUSTOMER_ID in (select ID from CUSTOMERS);由此可见,假定Session缓存中有n个orders集合代理类实例没有被初始化,那么当fetch属性为"subselect"时,Hibernate能够通过子查询的select语句,来整批量初始化orders集合代理类实例。
当fetch属性为"subselect"时,不必设置batch-size属性,即使设置了也会被忽略。
2.6.迫切左连接检索(fetch属性为"join")
Customer.hbm.xml:
<set name="orders" inverse="true" fetch="join">...</set>对于以下检索方法:
Customer customer = (Customer)session.get(Customer.class, new Long(1));会采用迫切左连接检索策略来检索所有关联的Order对象,执行以下select语句:
select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID = ORDERS.CUSTOMER_ID where CUSTOMERS.ID=1;Query的list()方法会忽略迫切左连接检索策略,对于以下检索方法:
List customers = session.createQuery("from Customer as c").list();Hibernate执行以下select语句:
select * from CUSTOMERS;
3.多对一和一对一关联的检索策略
Order.hbm.xml:
<many-to-one name="customer" column="CUSTOMER_ID" class="mypack.Customer" />
3.1.迫切左外连接检索(fetch属性为"join")
<many-to-one ... fetch="join" />对于以下检索方法:
Order order= (Order)session.get(Order.class, new Long(1));若Customer.hbm.xml中<set>元素的lazy属性为false,Hibernate执行以下select语句:
select * from ORDERS left outer join CUSTOMERS on ORDERS.CUSTOMER_ID = CUSTOMERS.ID where ORDERS.ID = 1;select * from ORDERS where CUSTOMER_ID = 1;若Customer.hbm.xml中<set>元素的lazy属性为true,Hibernate执行以下select语句:
select * from ORDERS left outer join CUSTOMERS on ORDERS.CUSTOMER_ID = CUSTOMERS.ID where ORDERS.ID = 1;Query的list()方法会忽略迫切左连接检索策略.
3.2.延迟检索(lazy属性为"proxy")
<many-to-one ... lazy="proxy" />对于以下检索方法:
Order order= (Order)session.get(Order.class, new Long(1));Hibernate执行以下select语句:
select * from ORDERS where ID = 1;当访问customer的getXXX()方法时,Hibernate执行:
select * from CUSTOMERS where ID = 1;若此时Customer.hbm.xml中<set>元素的lazy属性为false,Hibernate还执行:
select * from ORDERS where CUSTOMER_ID = 1;对于一对一关联,如果采用延迟加载策略,必须把<one-to-one>元素的constrained属性设为true:
<one-to-one name="customer" class="mypack.Customer" constrained="true" />
3.3.无代理延迟检索(lazy属性为"no-proxy")
对于以下程序代码:
Order order= (Order)session.get(Order.class, new Long(1)); //第一行Customer customer = order.getCustomer(); //第二行customer.getId(); //第三行customer.getName(); //第四行若Order对象的customer属性使用延迟检索(proxy),程序将在第四行初始化Customer代理类实例。
若Order对象的customer属性使用无代理延迟检索(no-proxy),程序将在第二行初始化Customer代理类实例。
由此可见,lazy属性为proxy时,可以更加延迟加载Customer对象。
3.4.立即检索(lazy属性为"false")
<many-to-one ... lazy="false" />对于以下程序代码:
Order order= (Order)session.get(Order.class, new Long(1));Hibernate执行以下select语句:
select * from ORDERS where ID = 1;select * from CUSTOMERS where ID = 1;若此时Customer.hbm.xml中<set>元素的lazy属性为false,Hibernate还执行:
select * from ORDERS where CUSTOMER_ID = 1;
3.5.批量延迟检索和批量立即检索(使用batch-size属性)
Order.hbm.xml中<many-to-one>元素的lazy属性为默认值proxy,设置Customer.hbm.xml中<class>元素的batch-size属性:
<class name="mypack.Customer" table="CUSTOMERS" batch-size="3" >当访问customer.getXXX()方法时,Hibernate会批量初始化三个Customer代理类实例:
select * from CUSTOMERS where ID in (1,2,3);假如Customer.hbm.xml文件中<class>和<set>元素都设置了batch-size属性:
<class name="mypack.Customer" table="CUSTOMERS" batch-size="3" ><set name="orders" inverse="true" batch-size="3" lazy="false" >并且Order.hbm.xml文件中<many-to-one>元素的lazy属性为false:
<many-to-one name="customer" column="CUSTOMER_ID" class="mypack.Customer" lazy="false" />那么对于以下程序时:
List orders = session.createQuery("from Order as c").list();Hibernate会执行以下select语句:
select * from ORDERS;select * from CUSTOMERS where ID in (1,2,3);select * from ORDERS where CUSTOMER_ID in (1,2,3);
4.控制迫切左外连接检索的深度
hibernate.cfg.xml:
<property name="max_fetch_depth">1</property>hibernate.properties:
hibernate.max_fetch_depth = 1
5.在应用程序中显示指定迫切左外连接检索策略
session.createQuery("from Customer as c left join fetch c.orders where c.id=1").list();会执行以下select语句:
select * from CUSTOMERS left outer join ORDERS on CUSTOMERS.ID = ORDERS.CUSTOMER_ID where CUSTOMER.ID = 1;
6.属性级别的检索策略
在对象-关系映射文件中,<property>和<component>元素的lazy属性如果为true,表示采用延迟检索策略,如果为false,表示采用立即检索策略,默认值为false。
属性级别的延迟检索策略适用于二进制大对象、字符串大对象以及大容量组件类型的属性。
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- Hibernate的检索策略
- 【Hibernate的检索策略】
- hibernate的检索策略
- Hibernate 的检索策略
- hibernate的检索策略
- hibernate的检索策略
- hibernate的检索策略
- eclipse自动补全的设置
- Android开发之Service
- 获取当前的日期时间 格式“yyyy-MM-dd HH:MM:SS"
- request和response中文乱码
- maven中dependencies与dependencyManagement的区别
- Hibernate 的检索策略
- unity全屏设置功能实现
- 创建表
- 使用EA画ER图并导出为图片
- 深入 String 类
- 锁屏下活动处理
- windows下安装redis
- mysql ALTER COLUMN MODIFY COLUMN CHANGE COLUMN 区别及用法
- [ML of Andrew Ng]Week 4 Neural Networks: Representation