前述
框架的出现是为了适应一些繁琐的重复的工作,从连接数据库到CRUD的实现,再到存储过程,事务。如果自己曾经从头到尾写过JDBC的实现,那么多半会怀疑人生。其实,在自己写JDBC的时候,可能很多人都违背DRY(Don’t Repeat Youself)的原则。框架出现的意义就是前辈们将自己踩过的坑填平,让后辈能够走得更平坦一些。
抓取策略
- 立即检索:立即查询,在执行查询语句时,立即查询所有数据。
- 延迟检索:延迟查询,在执行查询语句以后,在需要数据时再查询(懒加载)。
- 类级别检索:当前类的属性获取是否需要延迟。
get:立即检索
Load:延迟检索,默认情况,如果只使用OID的值不进行查询,如果要使用其他属性值,将进行查询。
Customer.hbm.xml
lazy默认为true,如果设置为false则会立即检索(不使用代理)。 - 关联级别检索:当前类关联的别一个类是否需要延迟。
一对多、多对多
容器提供了两个属性:fetch、lazy
以Customer和Order作为例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.hibernate3;
//Customer类及配置文件
public class Customer {
private Integer uid;
private String name;
private Set<Order> orderSet = new HashSet<Order>();
}
<hibernate-mapping>
<class name="com.hibernate3.Customer" table="customer">
<id name="uid" column="id" >
<generator class="native" />
</id>
<set name="orderSet" fetch="select" lazy="false">
<key column="customer_id" />
<one-to-many class="com.hibernate3.Order"/>
</set>
<property name="name" column="name" />
</class>
</hibernate-mapping>
1 | //Order类及其配置文件 |
1 | //业务逻辑 |
fetch:确定使用SQL格式(Join fetching、Select fetching、Subselect fetching)
Join:使用Outer join(外连接)来获取关联实例或者关联集合。当fetch=join时,lazy无效。
Select:如果没有指定lazy=false,禁止延迟加载,那么当真正访问关联关系时,会执行另一条SQL。
Subselect:另外发送一条SQL,抓去前面抓取到的所有实体对象的集合。当真正访问关联关系时,会执行另一条SQL。必须使用query,否则看不到效果lazy:关联对象是否延迟(Immediate、Lazy collection、Extra-lazy)
Immeaiate 立即抓取 (lazy=flase):当宿主被加载时,关联、集合属性被立即抓取。
Lazy collection fetching 延迟加载集合 (lazy=true):直到应用程序对集合进行了一次操作时,集合才被抓取(默认)。
Extra-lazy 集合抓取 (lazy=extra):对集合中的每个元素而言,都是直到需要时才进行访问数据库。(适用于非常大的集合)
fetch=”join”,lazy无效,底层会使用迫切左外连接,只是用一条select语句将所有的内容全部查询。
- fetch=”select” lazy=”false” ,立即查询,先查询客户select,再查询订单select。(同时执行两条语句)
- fetch=”select” lazy=”true” ,立即查询第一条语句,当需要Order数据时,再查询第二条。
- fetch=”select” lazy=”extra” ,立即查询第一条语句,当需要时,第二条语句使用聚合函数select count(*)查询,一共三条语句。
fetch=”subselect” lazy=”和上面一样” ,将使用子查询。必须使用Query,不然看不到效果。
业务逻辑变为:
//1 查询客户
List<Customer> allCustomer = session.createQuery("from Customer").list();
Customer customer = allCustomer.get(0);
System.out.println(customer.getCname());
//2 查询客户订单数
Set<Order> orderSet = customer.getOrderSet();
System.out.println(orderSet.size());
//3 查询客户订单详情
for (Order order : orderSet) {
System.out.println(order);
}
- fetch=”subselect” lazy=”false” ,同时执行两条select,第二条使用子查询(select …from…where id in(select…))
- fetch=”subselect” lazy=”true” ,第二条语句延迟查询。
- fetch=”subselect” lazy=”extra” ,第二条语句使用聚合函数,第三条语句使用子查询。