Hibernate 检索策略
Hibernate 的检索有两种:
1:立即检索。立即加载检索方法指定的对象。
2:延迟检索。延迟加载检索方法指定的对象。
好比老板让你去买包烟。然后1是拿着钱就去买了。2是先拿着钱。然后答应老板去买。等老板要抽烟的时候她才去买。
准备持久化类和相对应的映射文件。
package com.hibernate.strategy; import java.util.HashSet; import java.util.Set; public class Customer { private Integer customerId; private String customerName; private Set<Order> orders = new HashSet<Order>(); public Integer getCustomerId() { return customerId; } public void setCustomerId(Integer customerId) { this.customerId = customerId; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.hibernate.strategy"> <class name="Customer" table="CUSTOMERS" lazy="true" batch-size="5"> <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 name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC" > <key column="CUSTOMER_ID"></key> <one-to-many class="Order"/> </set> </class> </hibernate-mapping>
package com.hibernate.strategy; public class Order { private Integer orderId; private String orderName; private Customer customer; public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((orderId == null) ? 0 : orderId.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Order other = (Order) obj; if (orderId == null) { if (other.orderId != null) return false; } else if (!orderId.equals(other.orderId)) return false; return true; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.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 name="customer" class="Customer" column="CUSTOMER_ID" ></many-to-one> </class> </hibernate-mapping>
开始操作:
1:类级别的检索。通过设置<class>元素的lazy属性。
1):get方法获得类对象。
@Test public void testLeiStrategy(){ Customer customer=(Customer) session.get(Customer.class, 1); System.out.println(customer.getCustomerName()); System.out.println(customer.getClass()); }
解释:得到的是类本身。get是立即检索。
2):load方法
1 @Test 2 public void testLeiStrategy(){ 3 Customer customer=(Customer) session.load(Customer.class, 1); 4 System.out.println(customer.getCustomerName()); 5 System.out.println(customer.getClass()); 6 }
解释:返回的是一个代理对象。是延迟检索。
通过设置
<class name="Customer" table="CUSTOMERS" lazy="false">
懒惰相反。就是立即加载。返回的也是一个customer类对象。
lazy="false" 只对load有效。对get无效。
2:一对多。多对多检索
<set name="orders" table="ORDERS" inverse="true" order-by="ORDER_NAME DESC" > <key column="CUSTOMER_ID"></key> <one-to-many class="Order"/> </set>
因为无论是1对多,还是多对多。都是多的作为一个set集合,放到1 或多的中。其实就是对<set>设置。
1):lazy:主要决定orders集合被初始化的时机。一共有三个设置。true 是默认的。false 立即加载。 extra就是增加延迟加载。就是比延迟加载还狠。
2):fetch 决定初始化集合orders的查询语句的方式。
1>:默认:select 正常的查询。
2>:subselect 子查询的形式。因为是子查询。所以in()中需要order的ID。都要把set集合中的order都查询出来。batch-size会失效。
3>:join 检索1一端的时候。采用迫切左外连接去检索集合order。lazy会失效。
@Test public void testGetFeth(){ 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()); } } }
fetch="subselect" 查询的结果
解释:把order都给初始化了。
用select:
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_ from CUSTOMERS customer0_ 4 Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_0_1_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.ORDER_NAME as ORDER_NA2_1_0_, orders0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? order by orders0_.ORDER_NAME desc 2 Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_0_1_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.ORDER_NAME as ORDER_NA2_1_0_, orders0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? order by orders0_.ORDER_NAME desc 2 Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_0_1_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.ORDER_NAME as ORDER_NA2_1_0_, orders0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? order by orders0_.ORDER_NAME desc 3 Hibernate: select orders0_.CUSTOMER_ID as CUSTOMER3_0_1_, orders0_.ORDER_ID as ORDER_ID1_1_1_, orders0_.ORDER_ID as ORDER_ID1_1_0_, orders0_.ORDER_NAME as ORDER_NA2_1_0_, orders0_.CUSTOMER_ID as CUSTOMER3_1_0_ from ORDERS orders0_ where orders0_.CUSTOMER_ID=? order by orders0_.ORDER_NAME desc 1
需要1次查询一次。
3>:join
@Test public void testSetFetch2(){ Customer customer = (Customer) session.get(Customer.class, 1); System.out.println(customer.getOrders().size()); }
Hibernate: select customer0_.CUSTOMER_ID as CUSTOMER1_0_1_, customer0_.CUSTOMER_NAME as CUSTOMER2_0_1_, orders1_.CUSTOMER_ID as CUSTOMER3_0_3_, orders1_.ORDER_ID as ORDER_ID1_1_3_, orders1_.ORDER_ID as ORDER_ID1_1_0_, orders1_.ORDER_NAME as ORDER_NA2_1_0_, orders1_.CUSTOMER_ID as CUSTOMER3_1_0_ from CUSTOMERS customer0_ left outer join ORDERS orders1_ on customer0_.CUSTOMER_ID=orders1_.CUSTOMER_ID where customer0_.CUSTOMER_ID=? order by orders1_.ORDER_NAME desc 2
3:多对1 1对1
都是把1的一方放到多的。作为多的一个属性。
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>
false :默认的。
proxy :延迟加载。
no-proxy:无代理延迟加载。
fetch只有2个