1. 程式人生 > >hibernate關聯關係一對多

hibernate關聯關係一對多

1. 什麼是關聯(association)
  1.1 關聯指的是類之間的引用關係。如果類A與類B關聯,那麼被引用的類B將被定義為類A的屬性。例如:
      public class A{
        private B b = new B;
        public A(){}
      }
  1.2 關聯的分類:關聯可以分為一對一、一對多/多對一、多對多關聯
      關聯是有方向的
      
      訂單表、訂單項表
      select * from t_order t,t_orderItem m where t.oid = m.oid
      and .....
      
      
      class Order{
        private STIRNG OID;
        ...
        private Set<OrderItem> OrderItems; 
      }
      
      session.get(Order.class,1)


#關鍵點都在資料庫中的外來鍵上面,請好好理解下面這二句SQL和一對多及多對一的關係
#select * from Orders where cid=?   //這條SQL返回客戶對應的0-n個訂單
#select * from Customers where customerId=?  //這條SQL返回訂單對應的1個客戶
#通過這二條SQL不難看出,外來鍵在這裡有二個用途:查詢客戶的訂單,查詢訂單對應的客戶
2. 案例:如何建立客戶和訂單一對多雙向關聯
  2.1 先不建立客戶和訂單的關聯關係,定義實體及對映檔案,單獨執行儲存操作
  2.2 建立客戶到訂單的一對多關聯關係
      <set name="orders" inverse="true" cascade="save-update">
          <key column="cid"></key>
          <one-to-many class="entity.Order">
      </set>
      
  2.3 建立訂單到客戶的多對一關聯關係
      <many-to-one name="customer" class="entity.Customer" column="cid">
    
      <!--1.註釋 2.只讀-->
      <property name="cid" type="java.lang.Integer" column="cid" insert="false" update="false">
      </property>
 
  2.4 注意:在Hibernate當中定義實體物件的集合屬性時,只能使用介面而不能使用類


#insert屬性設定中主控方概念理解: 
3. 以客戶和訂單的一對多雙向關聯為例,講解Set元素中的cascade|inverse|outter-join|lazy屬性作用
  3.1 lazy:預設值為true,true延遲載入,false立即載入(一般設定為true,不使用立即載入,因為影響查詢效能)
  3.2 outter-join:預設值為false,true使用左外聯接查詢關聯的(但一般不用,因為當我們把該屬性設定為true時,所有的查詢語句都會預設左外聯,那樣效能不高)
  3.3 inverse:預設值為false,true表示將對方設定為主控方(一對多雙向關聯中一般將多方設定為主控方,這樣可以減少SQL語句的數量,減少多餘的操作)
  3.4 cascade:用來控制如何操作關聯的持久化物件的
    3.4.1 none:儲存,更新或刪除當前物件時,忽略其它關聯的物件
    3.4.2 save-update:儲存、更新時級聯儲存所有的臨時物件,並且級聯更新關聯的遊離物件
    3.4.3 delete:通過session的delete方法刪除當前物件,級聯刪除關聯的物件
    3.4.4 all:等於save-update操作+delete操作

  
  小結:
        多方的CRUD與沒有建立關聯關係之前的操作一致
        一方的CRUD與沒有建立關聯關係之前的操作有變化
          D:刪除一方之前先刪除多方
          C:級聯操作
          R:程式碼控制多方
 

4. 案例:選單物件的一對多雙向自關聯<!-- 多對一關係 -->

<!-- 多對一關係 -->
        <many-to-one name="order" class="com.zking.four.entity.Order" column="oid" ></many-to-one>

   <!-- 
            cascade:用來維護實體類之間的關係所用         save-update可修改增加
            inverse:關係是否由反方控制(是否由關聯的表來控制)
            lazy:是否為懶載入(延遲載入)     效能不佳
         -->
         <set name="orderItems" cascade="save-update" inverse="true">
             <!-- 關聯的表的id(外來鍵) -->
             <key column="oid"></key>
             <!-- 定義一對多關係 -->
             <one-to-many class="com.zking.four.entity.OrderItem"/>
         </set>

5. 如何將多方對映成一個有序的集合
   <!-- bag元素可以對映List集合,order-by屬性還可以用來排序(asc升序|desc降序),其它和set元素的使用一樣 -->
   <bag name="childMenus" inverse="true" lazy="true" outer-join="false" cascade="save-update" order-by="position asc">
        <key column="super_menu_id"></key>
    <one-to-many class="entity.Menu" />
   </bag>
   
   
   核心
  訂單表、訂單項

級聯新增
    外來鍵處理的三種方式
    1、刪除從表對應的實體類中的外來鍵屬性
    2、在配置的xml中外來鍵屬性上新增 insert=false,update=false的設定。
    3、在配置的xml中的manyToOne標籤中新增insert=false,update=false的設定。
    級聯新增    casecade=save-update 介紹


級聯查詢
    配置檔案介紹以及後臺sql的形成過程
    級聯查詢時的問題
    Lazy=true介紹    查單個時存在問題
    Lazy=false介紹    查所有時存在問題
    解決方案:通過欄位控制,強制載入。Hibernate.initialize()


普通刪除
    Order
    Add 講外來鍵的處理
    Get/list    order.getOrderItems.size講懶載入的處理,sql形成過程
    Del    將關係的處理中的刪除

 

package com.zking.four.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;

import com.zking.four.entity.Order;
import com.zking.four.entity.OrderItem;
import com.zking.two.util.SessionFactoryUtils;

public class OrderAction {
    public int save(Order order) {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
//        Order order2 = session.get(Order.class, order.getOrderId());
        session.save(order);
        transaction.commit();
        session.close();
        return order.getOrderId();
    }
    
    public Integer addOrderItem(OrderItem orderItem) {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
        Integer otid = (Integer) session.save(orderItem);
        transaction.commit();
        session.close();
        return otid;
    }
    
    public Integer addOrder(Order order) {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
        Integer oid = (Integer) session.save(order);
        transaction.commit();
        session.close();
        return oid;
    }
    
    
    public Order getOrder(Order order) {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
        Order order2 = session.get(Order.class, order.getOrderId());
        //判斷是否需要直接載入
        if(order2 != null && new Integer(1).equals(order.getInitOrderItems())) {
            Hibernate.initialize(order2.getOrderItems());
        }
        transaction.commit();
        session.close();
        return order2;
    }
    
    public List<Order> getOrderList() {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
        List orderList = session.createQuery("from Order").list();
        transaction.commit();
        session.close();
        return orderList;
    }
    
    public void delOrder(Order order) {
        Session session = SessionFactoryUtils.getSession();
        Transaction transaction = session.beginTransaction();
        Order order2 = session.get(Order.class, order.getOrderId());
        Set<OrderItem> orderItems = order2.getOrderItems();
        for (OrderItem oi : orderItems) {
            session.delete(oi);
        }
        session.delete(order2);
        transaction.commit();
        session.close();
    }
}

 

 

package com.zking.four.dao;

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

import org.junit.Before;
import org.junit.Test;

import com.zking.four.entity.Order;
import com.zking.four.entity.OrderItem;

public class OrderActionTest {
    OrderAction orderAction = new OrderAction();

    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testGet() {
        Order order = new Order();
        int save = orderAction.save(order);
        System.out.println(save);
    }
    
    @Test
    public void addGet() {
        OrderItem orderItem = new OrderItem();
        orderItem.setProduct_id(89);
        orderItem.setQuantity(78);
        //描述關係
        Order order = new Order();
        order.setOrderId(7);
        orderItem.setOrder(order);
        Integer addOrderItem = this.orderAction.addOrderItem(orderItem);
        System.out.println(addOrderItem);
        
    }
    
    
    @Test
    public void addOrder() {
        Order order = new Order();
        order.setOrderNo("P8");
        for (int i = 0; i < 6; i++) {
            OrderItem orderItem = new OrderItem();
            orderItem.setProduct_id(i);
            orderItem.setQuantity(i);
            
            //雙向關聯關係
            order.getOrderItems().add(orderItem);
            orderItem.setOrder(order);
        }
        Integer addOrder = this.orderAction.addOrder(order);
        System.out.println(addOrder);
    }
    
    @Test
    public void addOrdera() {
        Order order = new Order();
        order.setOrderNo("P12");
        Set<OrderItem> hashSet = new HashSet<>();
        for (int i = 0; i < 6; i++) {
            OrderItem orderItem = new OrderItem();
            orderItem.setProduct_id(i);
            orderItem.setQuantity(i);
            
            //雙向關聯關係
            orderItem.setOrder(order);
            hashSet.add(orderItem);
        }
        order.setOrderItems(hashSet);
        Integer addOrder = this.orderAction.addOrder(order);
        System.out.println(addOrder);
    }
    
    @Test
    public void getOrder() {
//        could not initialize proxy        懶載入
        Order order = new Order();
        order.setOrderId(8);
        //設定為非懶載入
        order.setInitOrderItems(1);
        Order order2 = this.orderAction.getOrder(order);
        System.out.println(order2.getOrderNo());
        System.out.println(order2.getOrderItems().getClass().getName());
        Set<OrderItem> orderItems = order2.getOrderItems();
        for (OrderItem o : orderItems) {
            System.out.println(o.getOrderItemId());
        }
    }
    
    
    
    @Test
    public void getOrderList() {
        List<Order> orderList = this.orderAction.getOrderList();
        for (Order order : orderList) {
            System.out.println(order.getOrderNo());
            Set<OrderItem> orderItems = order.getOrderItems();
            for (OrderItem o : orderItems) {
                System.out.println(o.getOrderItemId());
            }
        }
    }
    
    
    
    @Test
    public void DelOrder() {
        Order order = new Order();
        order.setOrderId(11);
        this.orderAction.delOrder(order);
        
    }

}

package com.zking.four.entity;

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

public class Order {
    private Integer orderId;
    private    String orderNo;
    
    //定義一對多的關係時一定要採用介面的方式,不能用實現類(用set,不能用hashset)
    private Set<OrderItem> orderItems = new HashSet<>();
    
    private Integer initOrderItems = 0;//0代表懶載入      1代表立即載入
    
    
    public Integer getInitOrderItems() {
        return initOrderItems;
    }
    public void setInitOrderItems(Integer initOrderItems) {
        this.initOrderItems = initOrderItems;
    }
    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;
    }
    
}

 

package com.zking.four.entity;

public class OrderItem {
    private Integer orderItemId;
    private Integer product_id;
    private Integer quantity;
    private Integer oid;
    
    //一對一
    private Order order = new 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 getProduct_id() {
        return product_id;
    }
    public void setProduct_id(Integer product_id) {
        this.product_id = product_id;
    }
    public Integer getQuantity() {
        return quantity;
    }
    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }
    public Integer getOid() {
        return oid;
    }
    public void setOid(Integer oid) {
        this.oid = oid;
    }
    
}