1. 程式人生 > >hibernate一對多,多對多對映

hibernate一對多,多對多對映

1.什麼是關聯?

關聯指的是類之間的引用關係。如果類A與類B關聯,那麼被引用的類B將被定義為類A的屬性。例如:
 

    public class A{
        private B b = new B;
        public A(){}
      }

1.2 關聯的分類:

關聯可以分為一對一、一對多/多對一、多對多關聯  關聯是有方向的

#關鍵點都在資料庫中的外來鍵上面,請好好理解下面這二句SQL和一對多及多對一的關係
#select * from Orders where cid=?   //這條SQL返回客戶對應的0-n個訂單
#select * from Customers where customerId=?  //這條SQL返回訂單對應的1個客戶
#通過這二條SQL不難看出,外來鍵在這裡有二個用途:查詢客戶的訂單,查詢訂單對應的客戶

2.那麼如何建立一個一對多的關聯呢

因為hibernate是通過實體類操作資料庫的,這裡就貼實體類的程式碼

訂單類

public class Order {

    private int order_id;
    private String order_no;

    //變數屬性一定要用介面接收
    //描述一個訂單對應多個訂單項
    public Set<OrderItem> getOrderitems() {
        return orderitems;
    }

    public void setOrderitems(Set<OrderItem> orderitems) {
        this.orderitems = orderitems;
    }

    private Integer initorderitems = 0;//0懶載入 1強制載入

    public Integer getInitorderitems() {

        return initorderitems;
    }

    public void setInitorderitems(Integer initorderitems) {
        this.initorderitems = initorderitems;
    }

    private Set<OrderItem> orderitems = new HashSet<>();

    public int getOrder_id() {
        return order_id;
    }

    public void setOrder_id(int order_id) {
        this.order_id = order_id;
    }

    public String getOrder_no() {
        return order_no;
    }

    public void setOrder_no(String order_no) {
        this.order_no = order_no;
    }
}

訂單項類

public class OrderItem {
    private int order_item_id;
    private int product_id;
    private int quantity;
    private int oid;
//多個訂單項對應一個訂單
    private Order order;

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public int getOrder_item_id() {
        return order_item_id;
    }

    public void setOrder_item_id(int order_item_id) {
        this.order_item_id = order_item_id;
    }

    public int getProduct_id() {
        return product_id;
    }

    public void setProduct_id(int product_id) {
        this.product_id = product_id;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public int getOid() {
        return oid;
    }

    public void setOid(int oid) {
        this.oid = oid;
    }
}

 

然後這裡普通的對映就不貼程式碼啦,請去看以前的部落格

因為訂單和訂單項是一對多的關係

<!--cascade:級聯屬性配置 建議不配置del可能會造成迭代刪除-->
		<!--inverse:關聯關係交給別人維護麼?-->
		<set name="orderitems" inverse="true" cascade="save-update">

			<!--對應外來鍵-->
			<key column="oid"></key>
			<one-to-many class="com.zking.three.OrderItem"></one-to-many>
		</set>
		<!--對應list集合-->
		<!--<list name="">-->
			<!--<key></key>-->
		<!---->
		<!--</list>-->
		<!--<bag name="">-->
			<!--<key></key>-->

		<!--</bag>-->

訂單項是多對一 

<many-to-one insert="false" update="false" name="order" class="com.zking.three.Order" column="oid"></many-to-one>

在這裡可能會報一個錯Repeated column in mapping for entity: com.zking.three.OrderItem column: oid
解決方法 加上insert="false" update="false"  或者加在oid屬性中或者在實體類中刪除哦id屬性都可一解決

 3.1 lazy:預設值為true,true延遲載入,false立即載入(一般設定為true,不使用立即載入,因為影響查詢效能)查詢的時候如果報錯有很大的可能是因為懶載入的原因

Lazy=true介紹    查單個時存在問題
    Lazy=false介紹    查所有時存在問題

所以使用Hibernate.initialize()來強制載入某個屬性來解決

   public Order get(Order order){
        Session session = SessionFactoryUtils.openSession();
        Transaction transaction = session.beginTransaction();
        Order o=session.get(order.getClass(),order.getOrder_id());
        if(o!=null&&order.getInitorderitems().equals(new Integer(1))){
            Hibernate.initialize(o.getOrderitems());
        }
        transaction.commit();
        session.close();
        return o;
    }


  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方法刪除當前物件,級聯刪除關聯的物件

 

4.多對多

舉個例子一本書可以對應多個類別,一個類別也可以對應多本書這就是多對多

 

<!--name:指的是當前對映實體的屬性-->
		<!--table:對應的是中間表-->
		<!--關聯關係是否交給對方維護 只要有一方維護即可-->
		<!--inverse="true" cascade="save-update"只要一方維護就好-->
		<set name="categorys" table="t_hibernate_book_category" >
			<!--指的是中間表字段(與當前對映實體對應的表的主鍵相關聯的id)-->
			<key column="bid"></key>
			<!-- class:多方的全類名
            cloumn:與多方主鍵相關聯的欄位
            -->
			<many-to-many class="com.zking.four.Category" column="cid"></many-to-many>
		</set>
	</class>
     <!--name:指的是當前對映實體的屬性-->
      <!--table:對應的是中間表-->
      <!--關聯關係是否交給對方維護-->
<set name="books" table="t_hibernate_book_category" inverse="true" cascade="save-update">
   <!--指的是中間表字段(與當前對映實體對應的表的主鍵相關聯的id)-->
   <key column="cid"></key>
   <!-- class:多方的全類名
   cloumn:與多方主鍵相關聯的欄位
   -->
   <many-to-many class="com.zking.four.Book" column="bid"></many-to-many>
   </set>

4.3. 多對多關係注意事項
  4.3.1 一定要定義一個主控方
  4.3.2 多對多刪除
    4.3.2.1 主控方直接刪除
    4.3.2.2 被控方先通過主控方解除多對多關係,再刪除被控方
    4.3.2.3 禁用級聯刪除
  4.3.3 關聯關係編輯,不需要直接操作橋接表,hibernate的主控方會自動維護
  

其實用的最多的還是一對多的關係,多對多可以看成兩個一對多