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;
}
}