1. 程式人生 > >Hibernate:級聯查詢

Hibernate:級聯查詢

案例:訂單類和訂單項類

級聯查詢時的問題     Lazy=true介紹    查單個時存在問題       Lazy=false介紹    查所有時存在問題       在set裡把lazy=“false”也可以所報的錯(com.zking.four.entity.Order.orderItems,       could not initialize proxy - no Session)   <set lazy="false" name="orderItems" cascade="save-update" inverse="true">    解決方案:通過欄位控制,強制載入。Hibernate.initialize()

不在order類加initOrderItems欄位時,會報錯

 

1.order類

package com.zking.four.entity;

import java.util.HashSet;
import java.util.Set;

public class Order {
	
	private Integer orderId;
	private String orderNo;
	
	//定義一對多的關係時一定需要採用介面方式,不許使用實現類
	//implements java.util.Set  代理實現的是set介面
	private Set<OrderItem> orderItems=new HashSet<OrderItem>();
	
	private Integer initOrderItem=0;//0代表懶載入   1代表立即載入
	
	public Integer getInitOrderItem() {
		return initOrderItem;
	}
	public void setInitOrderItem(Integer initOrderItem) {
		this.initOrderItem = initOrderItem;
	}
	public Set<OrderItem> getOrderItems() {
		return orderItems;
	}
	public void setOrderItems(Set<OrderItem> orderItems) {
		this.orderItems = orderItems;
	}
	public Integer getOrderId() {
		return orderId;
	}
	public void setOrderId(Integer orderId) {
		this.orderId = orderId;
	}
	public String getOrderNo() {
		return orderNo;
	}
	public void setOrderNo(String orderNo) {
		this.orderNo = orderNo;
	}
	
	
	

}

2.orderItem類

package com.zking.four.entity;

public class OrderItem {
	
	private Integer orderItemId;
	private Integer productId;
	private Integer quaneity;
	private Integer oid;
	
	private Order order;
	
	public Order getOrder() {
		return order;
	}
	public void setOrder(Order order) {
		this.order = order;
	}
	public Integer getOrderItemId() {
		return orderItemId;
	}
	public void setOrderItemId(Integer orderItemId) {
		this.orderItemId = orderItemId;
	}
	public Integer getProductId() {
		return productId;
	}
	public void setProductId(Integer productId) {
		this.productId = productId;
	}
	public Integer getQuaneity() {
		return quaneity;
	}
	public void setQuaneity(Integer quaneity) {
		this.quaneity = quaneity;
	}
	public Integer getOid() {
		return oid;
	}
	public void setOid(Integer oid) {
		this.oid = oid;
	}
	
	

}

3.order.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    	<class table="t_hibernate_order" name="com.zking.four.entity.Order">
    		<id name="orderId" type="java.lang.Integer" column="order_id ">
    			<generator class="increment"></generator>
    		</id>
    		<property name="orderNo" type="java.lang.String" column="order_no "></property>
    		
    		<!-- 
    		name:實體類的類屬性
    		cascade:用來配置維護實體類之間的關係所用
    		inverse:(inverse="true")關係交由反方控制    即訂單項   因為現在配置的是訂單,所以反方是訂單項
    		(inverse="true") 關係由自己控制   訂單
    		lazy="false":立即載入
    		 -->
    		<set lazy="false" name="orderItems" cascade="save-update" inverse="true">
    			<!-- 訂單項外來鍵 -->
    			<key column="oid"></key>
    			<!-- 一個訂單對應多個訂單項 -->
    			<one-to-many class="com.zking.four.entity.OrderItem"></one-to-many>
    		</set>
    	</class>
    </hibernate-mapping>

4.orderItem.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
    	<class table="t_hibernate_order_item" name="com.zking.four.entity.OrderItem">
    		<id name="orderItemId" type="java.lang.Integer" column="order_item_id ">
    			<generator class="increment"></generator>
    		</id>
    		<property name="productId" type="java.lang.Integer" column="product_id "></property>
    		<property name="quaneity" type="java.lang.Integer" column="quantity "></property>
    		
    		<property name="oid" type="java.lang.Integer" column="oid" insert="false" update="false"></property>
    		
    		
    	<many-to-one name="order" class="com.zking.four.entity.Order" column="oid"></many-to-one>
    	
    	</class>    	  	
    	
    </hibernate-mapping>

5.dao方法

public class OrderDao(){
    //單個查
	public Order getOrder(Order order) {
		Session session = SessionFactoryUtils.getSession();
		Transaction transaction = session.beginTransaction();
		Order o = session.get(Order.class,order.getOrderId());
		if(o!=null&&new Integer(1).equals(order.getInitOrderItem())) {
			Hibernate.initialize(o.getOrderItems());  //預設強制載入
		}
		transaction.commit();
		session.close();
		return o;
	}


    //查所有
	public List<Order> listOrder() {
		Session session = SessionFactoryUtils.getSession();
		Transaction transaction = session.beginTransaction();
		System.out.println(123);
		List list = session.createQuery("from Order").list();
		System.out.println(345);
		transaction.commit();
		session.close();
		return list;
	}
}

6.測試類:


public class OrderDaoTest {

	private OrderDao orderDao=new OrderDao();
	private OrderItem orderItem=new OrderItem();
	private Order order=new Order();
        /**
	 * com.zking.four.entity.Order.orderItems,
	 *  could not initialize proxy - no Session
	 *  懶載入
	 *  
	 *  hibernate3 以後預設是懶載入     效能調優      關聯的東西出不來
	 *  
	 *  
	 */
	@Test
	public void testGetOrder() {
		order.setOrderId(2);
		order.setInitOrderItem(1);
		Order o = this.orderDao.getOrder(order);
		System.out.println(o.getOrderNo());
		System.out.println(o.getOrderItems().size());
		for (OrderItem oi : o.getOrderItems()) {
			System.out.println(oi.getProductId());
		}
	}

        /**
	 * 
	 * 在單查訂單的時候,會預設查詢訂單項,sql語句就會執行很多次    耗效能
	 * 
	 * Lazy=false   可以解決報錯問題  使懶載入變為立即載入   但是效能差
	 */
	@Test
	public void testListOrder() {
		List<Order> listOrder = this.orderDao.listOrder();
		for (Order o : listOrder) {
			System.out.println(o.getOrderNo());
			System.out.println(o.getOrderItems().size());
			for (OrderItem oi : o.getOrderItems()) {
				System.out.println(oi.getProductId());
			}
		}
	}

}

單個查結果:

查所有結果:

查詢所有,是有n條資料就執行了n+1次sql查詢語句(一條訂單查詢,n條訂單項查詢)

查詢的解決:只要把set裡的lazy設定為false使懶載入變成立即載入就可以實現查所有的方法了,但是因為sql語句執行的多了,功能效能就差了

<set lazy="false" name="orderItems" cascade="save-update" inverse="true">