类级别的检索策略
- 类级别可选的检索策略包括立即检索和延迟检索, 默认为延迟检索
- 延迟检索仅对 Session 的 load()方法有效,(无论 <class> 元素的 lazy 属性是 true 还是 false, Session 的 get() 方法及 Query 的 list() 方法在类级别总是使用立即检索策略)
- 配置方式: 类级别的检索策略可以通过 <class> 元素的 lazy 属性进行设置
- 示例
//*.hbm.xml中<class>元素设置 lazy 属性
<hibernate-mapping package="com.atguigu.hibernate.strategy">
<class name="Customer" table="CUSTOMERS" lazy="true">
<id name="customerId" type="java.lang.Integer">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id>
...
@Test
public void testClassLevelStrategy(){
Customer customer = (Customer) session.load(Customer.class, 1);
System.out.println(customer.getClass());
System.out.println(customer.getCustomerId());
System.out.println(customer.getCustomerName());
}
一对多和多对多的检索策略
- 配置方式:用 <set> 元素来配置一对多关联及多对多关联关系. <set> 元素有 lazy 、 fetch、batch-size 属性
- lazy 取值为 true、 false 或 extra,默认为 true(extra:采用增强的延迟检索策略)
- fetch 取值为 select、subselect 或 join,默认取值 select(取值为 select 或 subselect :决定初始化查询的语句形式;取值为 join :采用迫切左外链接的形式查询语句,忽略 lazy 属性)
- batch-size 属性 设定批量检索的数量,批量检索能减少 SELECT 语句的数目, 提高延迟检索或立即检索的运行性能(默认值为1)
- 示例 1:
//*.hbm.xml中配置
<hibernate-mapping package="com.atguigu.hibernate.strategy">
<class name="Customer" table="CUSTOMERS">
<id name="customerId" type="java.lang.Integer">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id>
<property name="customerName" type="java.lang.String">
<column name="CUSTOMER_NAME" />
</property>
//set中配置 lazy、fetch、batch-size
<set name="orders" table="ORDERS"
inverse="true" lazy="true"
batch-size="2" fetch="subselect">
<key column="CUSTOMER_ID"></key>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
//---------------set 的 lazy 属性------------------
//1. 1-n 或 n-n 的集合属性默认使用懒加载检索策略.
//2. 可以通过设置 set 的 lazy 属性来修改默认的检索策略. 默认为 true
//并不建议设置为 false.
//3. lazy 还可以设置为 extra. 增强的延迟检索. 该取值会尽可能的延迟集合初始化的时机!
//4. lazy 属性值为 true 时,应用程序第一次访问集合属性: iterator(), size(), isEmpty(), contains() 等方法以及调用 Hibernate.initialize() 方法时 会初始化集合代理类实例
//5. lazy 属性值为 extra 时,当程序第一次访问 orders 属性的 iterator() 方法时, 会导致 orders 集合代理类实例的初始化;当程序第一次访问 order 属性的 size(), contains() 和 isEmpty() 方法时, Hibernate 不会初始化 orders 集合类的实例, 仅通过特定的 select 语句查询必要的信息, 不会检索所有的 Order 对象
@Test
public void testOne2ManyLevelStrategy(){
Customer customer = (Customer) session.get(Customer.class, 1);
System.out.println(customer.getCustomerName());
System.out.println(customer.getOrders().size());
Order order = new Order();
order.setOrderId(1);
System.out.println(customer.getOrders().contains(order));
Hibernate.initialize(customer.getOrders());
}
- 示例 2:
@Test
public void testSetFetch(){
List<Customer> customers = session.createQuery("FROM Customer").list();
System.out.println(customers.size());
for(Customer customer: customers){
if(customer.getOrders() != null)
System.out.println(customer.getOrders().size());
}
//set 集合的 fetch 属性: 确定初始化 orders 集合的方式.
//1. 默认值为 select. 通过正常的方式来初始化 set 元素
//2. 可以取值为 subselect. 通过子查询的方式来初始化所有的 set 集合. 子查询
//作为 where 子句的 in 的条件出现, 子查询查询所有 1 的一端的 ID. 此时 lazy 有效.
//但 batch-size 失效.
//3. 若取值为 join. 则
//3.1 在加载 1 的一端的对象时, 使用迫切左外连接(使用左外链接进行查询, 且把集合属性进行初始化)的方式检索 n 的一端的集合属性
//3.2 忽略 lazy 属性.
//3.3 HQL 查询忽略 fetch=join 的取值,依旧采用 延迟加载策略
}
多对一和一对一关联的检索策略
- 配置方式:和 <set> 一样, <many-to-one> 元素也有一个 lazy 属性和 fetch 属性以及 batch-size 属性.
- lazy 属性取值为 proxy(延迟检索)、no-proxy(无代理延迟检索),false(立即检索);默认取值 proxy;
- fetch 属性取值:select、join(迫切左外连接检索方式),默认取值为 select;
- 示例:
// *.hbm.xml中 配置
<hibernate-mapping package="com.atguigu.hibernate.strategy">
<class name="Order" table="ORDERS">
<id name="orderId" type="java.lang.Integer">
<column name="ORDER_ID" />
<generator class="native" />
</id>
<property name="orderName" type="java.lang.String">
<column name="ORDER_NAME" />
</property>
//<many-to-one>中配置lazy、fetch
<many-to-one
name="customer" class="Customer"
column="CUSTOMER_ID"
lazy="false"
fetch="join"></many-to-one>
</class>
</hibernate-mapping>
@Test
public void testMany2OneStrategy(){
// Order order = (Order) session.get(Order.class, 1);
// System.out.println(order.getCustomer().getCustomerName());
List<Order> orders = session.createQuery("FROM Order o").list();
for(Order order: orders){
if(order.getCustomer() != null){
System.out.println(order.getCustomer().getCustomerName());
}
}
//1. lazy 取值为 proxy 和 false 分别代表对应对应的属性采用延迟检索和立即检索
//2. fetch 取值为 join, 表示使用迫切左外连接的方式初始化 n 关联的 1 的一端的属性
//忽略 lazy 属性.
//3. batch-size, 该属性需要设置在 1 那一端的 class 元素中:
//<class name="Customer" table="CUSTOMERS" lazy="true" batch-size="5">
//作用: 一次初始化 1 的这一段代理对象的个数.
}