一對多(級聯新增,級聯查詢,刪除)
1. 什麼是關聯(association) 1.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. 案例:如何建立客戶和訂單一對多雙向關聯 2.1 先不建立客戶和訂單的關聯關係,定義實體及對映檔案,單獨執行儲存操作 2.2 建立客戶到訂單的一對多關聯關係<!-- cascade:用來配置維護實體類之間的關係所用 inverse:關係交由反方控制 --> <set name="orderItems" cascade="save-update" inverse="true"> <!-- 填外來鍵 --> <key column="oid"></key> <one-to-many class="com.zking.four.entity.OrderItem"/> </set>
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:程式碼控制多方
級聯新增 外來鍵處理的三種方式 1、刪除從表對應的實體類中的外來鍵屬性 2、在配置的xml中外來鍵屬性上新增 insert=false,update=false的設定。 3、在配置的xml中的manyToOne標籤中新增insert=false,update=false的設定。 級聯新增 casecade=save-update 介紹
public void testAddOrder() { Order order = new Order(); order.setOrderNo("p1"); OrderItem orderItem; for (int i = 1; i < 2; i++) { orderItem = new OrderItem(); orderItem.setProductId(i); orderItem.setQuantity(i); order.getOrderItems().add(orderItem); orderItem.setOrder(order); } this.orderDao.addOrder(order); }
級聯查詢 配置檔案介紹以及後臺sql的形成過程 級聯查詢時的問題 Lazy=true介紹 查單個時存在問題 Lazy=false介紹 查所有時存在問題 解決方案:通過欄位控制,強制載入。Hibernate.initialize()
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.getInitOrderItems())) { Hibernate.initialize(o.getOrderItems()); } transaction.commit(); session.close(); return o; }
普通刪除 Order Add 講外來鍵的處理 Get/list order.getOrderItems.size講懶載入的處理,sql形成過程 Del 將關係的處理中的刪除 public void deleteOrder(Order order) { Session session = SessionFactoryUtils.getSession(); Transaction transaction = session.beginTransaction(); Order o = session.get(Order.class, order.getOrderId()); for (OrderItem ot : o.getOrderItems()) { session.delete(ot); } session.delete(o); transaction.commit(); session.close(); }
報錯:Repeated column in mapping for entity:com.zking.four.entity.OrderItem column: oid (should be mapped with insert="false" update="false"):同一個欄位被映射了兩次