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的主控方會自動維護
其實用的最多的還是一對多的關係,多對多可以看成兩個一對多