1. 程式人生 > >雙向一對多(多對一)@OneToMany或@ManyToOne的用法

雙向一對多(多對一)@OneToMany或@ManyToOne的用法

例如我們用一個例子來開啟JPA的一對多和多對一的學習。

  比如你去噹噹網上買書籍,噹噹網就給你一個訂單。
  通過上面的業務活動描述你可以分析得出:一個訂單可以包含一個或多個訂單項.那麼我們將將訂單和訂單項設計關係為(1:N)一對多的關係(排除0)。得出關係我們就使用JPA來實現這個關係(關於建立JPA和基本的配置我就不再說了,如果不明白請看JPA入門篇)。

首先建立訂單實體類

import java.util.HashSet;   
import java.util.Set;   
  
import javax.persistence.CascadeType;   
import javax.persistence.Column;   
import javax.persistence.Entity;   
import javax.persistence.Id;   
import javax.persistence.OneToMany;   
import javax.persistence.Table;   
  
@Entity  
@Table(name="orders")   
public class Order {   
       
    private String orderid;   
    private Float amount = 0f;   
    private Set<OrderItem> items = new HashSet<OrderItem>();   
  
    @Id  
    @Column(length = 12)   
    public String getOrderid() {   
        return orderid;   
    }   
  
    public void setOrderid(String orderid) {   
        this.orderid = orderid;   
    }   
  
    @Column(nullable = false)   
    public Float getAmount() {   
        return amount;   
    }   
  
    public void setAmount(Float amount) {   
        this.amount = amount;   
    }   
  
    @OneToMany(cascade = { CascadeType.REFRESH, CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REMOVE },mappedBy ="order") //這裡配置關係,並且確定關係維護端和被維護端。mappBy表示關係被維護端,只有關係端有權去更新外來鍵。這裡還有注意OneToMany預設的載入方式是賴載入。當看到設定關係中最後一個單詞是Many,那麼該載入預設為懶載入   
    public Set<OrderItem> getItems() {   
        return items;   
    }   
  
    public void setItems(Set<OrderItem> items) {   
        this.items = items;   
    }   
       
         /**   
           *該方法用於向order中加order項   
          /*   
    public void addOrderItem(OrderItem orderItem){   
        orderItem.setOrder(this);//用關係維護端來維護關係   
        this.items.add(orderItem);   
    }   
  
} 
訂單項的實體類
import javax.persistence.CascadeType;   
import javax.persistence.Column;   
import javax.persistence.Entity;   
import javax.persistence.GeneratedValue;   
import javax.persistence.Id;   
import javax.persistence.JoinColumn;   
import javax.persistence.ManyToOne;   
  
@Entity  
public class OrderItem {   
    private Integer id;   
    private String productName;   
    private Float sellPrice = 0f;   
    private Order order;   
  
    @Id  
    @GeneratedValue  
    public Integer getId() {   
        return id;   
    }   
  
    public void setId(Integer id) {   
        this.id = id;   
    }   
  
    @Column(length = 40, nullable = false)   
    public String getProductName() {   
        return productName;   
    }   
  
    public void setProductName(String productName) {   
        this.productName = productName;   
    }   
  
    @Column(nullable = false)   
    public Float getSellPrice() {   
        return sellPrice;   
    }   
  
    public void setSellPrice(Float sellPrice) {   
        this.sellPrice = sellPrice;   
    }   
  
    @ManyToOne(cascade = {CascadeType.MERGE,CascadeType.REFRESH }, optional = true)   
    @JoinColumn(name="order_id")//這裡設定JoinColum設定了外來鍵的名字,並且orderItem是關係維護端  
    public Order getOrder() {   
        return order;   
    }   
  
    public void setOrder(Order order) {   
        this.order = order;   
    }   
  
}  
下面看看測試類
import javax.persistence.EntityManager;   
import javax.persistence.EntityManagerFactory;   
import javax.persistence.Persistence;   
  
import org.junit.BeforeClass;   
import org.junit.Test;   
  
import cn.itcast.bean.Order;   
import cn.itcast.bean.OrderItem;   
  
public class OneToManyTest {   
  
    @BeforeClass  
    public static void setUpBeforeClass() throws Exception {   
    }   
    @Test public void addOrder(){   
         EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");   
         EntityManager em = factory.createEntityManager();   
         em.getTransaction().begin(); // start transaction   
            
                   Order order = new Order();    
         order.setAmount(34f);    
         order.setOrderid("00001");   
                      
                   //order中包含的OrderItem項OrderItem1,OrderItem2   
         OrderItem orderItem1 = new OrderItem();   
         orderItem1.setProductName("書");   
         orderItem1.setSellPrice(22f);   
         order.addOrderItem(orderItem1); //add orderitem in order   
            
         OrderItem orderItem2 = new OrderItem();   
         orderItem2.setProductName("籃球");   
         orderItem2.setSellPrice(100f);   
         order.addOrderItem(orderItem2);   
            
         em.persist(order); //persist order object   
         em.getTransaction().commit(); //commit transaction   
         em.close();   
         factory.close();   
    }   
} 

雙向一對多關係,一是關係維護端(owner side),多是關係被維護端(inverse side)。在關係被維護端需要通過@JoinColumn建立外來鍵列指向關係維護端的主鍵列

publicclass Order implements Serializable { privateSet<OrderItem> orderItems = new HashSet<OrderItem>(); 。。。。 @OneToMany(mappedBy="order",cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OrderBy(value = "id ASC") public Set<OrderItem> getOrderItems() { returnorderItems;      } } publicclass OrderItem implements Serializable { private Order order; 。。。。 @ManyToOne(cascade=CascadeType.REFRESH,optional=false) @JoinColumn(name = "order_id") public Order getOrder() { returnorder;      } } @OrderBy(value = "id ASC") 指明載入OrderItem 時按id 的升序排序 @OneToMany的屬性 1>targetEntity 定義關係類的型別,預設是該成員屬性對應的類型別,所以通常不需要提供定義 2>mappedBy 定義類之間的雙向關係。如果類之間是單向關係,不需要提供定義如果類和類之間形成雙向關係,我們就需要使用這個屬性進行定義,否則可能引起資料一致性的問題 該屬性的值是“多”方class裡的“一”方的變數名 3>cascade 該屬性定義類和類之間的級聯關係。定義的級聯關係將被容器視為對當前類物件及其關聯類物件採取相同的操作,而且這種關係是遞迴呼叫的。舉個例子:Order OrderItem有級聯關係,那麼刪除Order時將同時刪除它所對應的OrderItem物件。而如果OrderItem還和其他的物件之間有級聯關係,那麼這樣的操作會一直遞迴執行下去。 cascade的值只能從CascadeType.PERSIST(級聯新建)、CascadeType.REMOVE(級聯刪除)、CascadeType.REFRESH(級聯重新整理)、CascadeType.MERGE(級聯更新)中選擇一個或多個。還有一個選擇是使用CascadeType.ALL,表示選擇全部四項。 4>fatch 可選擇項包括:FetchType.EAGERFetchType.LAZY。前者表示關係類(本例是OrderItem )在主類(本例是Order)載入的時候同時載入,後者表示關係類在被訪問時才載入。預設值是FetchType.LAZY @JoinColumn(name = "order_id")註釋指定OrderItem對映表的order_id列作為外來鍵與Order 對映表的主鍵列關聯。 @ManyToOne:指明OrderItem和Order之間為多對一關係。 @ManyToOne註釋有四個屬性:targetEntity、cascade、fetch 和optional,前三個屬性的具體含義和@OneToMany的同名屬性相同,但@ManyToOne的fetch 屬性預設值是FetchType.EAGER optional屬性是定義該關聯類是否必須存在值為false 時,關聯類雙方都必須存在,如果關係被維護端不存在,查詢的結果為null。值為true 時, 關係被維護端可以不存在,查詢的結果仍然會返回關係維護端,在關係維護端中指向關係被維護端的屬性為nulloptional屬性的預設值是trueoptional 屬性實際上指定關聯類與被關聯類的join 查詢關係,如optional=false 時join 查詢關係為inner join, optional=true 時join 查詢關係為left join。下面程式碼片斷解釋如下: 有一點需要強調:當業務方法需要把一個實體Bean作為引數返回給客戶端時,除了實體Bean本身需要實現Serializable 介面之外,如果關聯類(OrderItem)是延遲載入,還需在返回實體Bean之前通過訪問關聯類的方式載入關聯類(見下例)。否則在客戶端訪問關聯類時將會丟擲載入例外。 public Order getOrderByID(Integer orderid) {         Order order = em.find(Order.class, orderid);         //!!!!!因為是延遲載入,通過執行size()這種方式獲取訂單下的所有訂單項         order.getOrderItems().size(); return order;      } 另外不管是否延遲載入,通過join fetch 關聯語句都可顯式載入關聯類,如下例: public List getAllOrder() {          Query query = em.createQuery("select DISTINCT o from Order o inner join fetch o.orderItems order by o.orderid");          List result = query.getResultList(); return result;      }


轉自:

相關推薦

雙向一對@OneToMany@ManyToOne用法

例如我們用一個例子來開啟JPA的一對多和多對一的學習。   比如你去噹噹網上買書籍,噹噹網就給你一個訂單。  通過上面的業務活動描述你可以分析得出:一個訂單可以包含一個或多個訂單項.那麼我們將將訂單和訂單項設計關係為(1:N)一對多的關係(排除0)。得出關係我們就使用JPA

MyBatis 關聯查詢一對 &

1、一對多 舉個例子:一個國家有很多人。一對多 1)表結構 -- 國家country CREATE TABLE `country` ( `cid` int(5) NOT NULL AUTO_INCREMENT, `cname` varchar(20) NOT NULL, PR

hibernate 關聯關係配置一對

Hibernate 關聯關係:        1. 什麼是關聯(association)            1.1 關聯指的是類之間的引用關係。如果類A與類B關聯,那麼被引用的類B將被定義為類

hibernate關聯關係一對

1.什麼是關聯關係? 關聯關係是指兩個實體或者表有相互關聯,比如在學生表中,學生表有班級id,那麼學生表中的班級id就關聯班級表中班級Id欄位。因此關聯關係,可以看成是一種外來鍵關係。 2.為什麼要有關聯關係? 為了實現級聯操作,刪除班級中某個學生,會連帶刪除學生表中的

MyBatis 關聯查詢一對 &

1、一對多 舉個例子:一個國家有很多人。一對多 1)表結構 -- 國家country CREATE TABLE `country` ( `cid` int(5) NOT NULL AUTO_INCREMENT, `cname` varchar(20) NOT N

MyBatis 關聯查詢 自關聯 一對

所謂自關聯是指,自己即充當一方,又充當多方。其實就是普通1:n 和 n:1的變形 1、一對多 1)表結構 -- 新聞欄目 CREATE TABLE `news` ( `id` int(5) NOT NULL AUTO_INCREMENT, `name` varcha

Python3基礎之三十 執行緒&程序

一、多執行緒 Threading 多執行緒 Threading 是一種讓程式擁有分身效果. 能同時處理多件事情. 一般的程式只能從上到下一行行執行程式碼, 不過多執行緒 (Threading)就能打破這種限制. 讓你的程式鮮活起來. 二、多程序 Multiprocessing

java執行緒快速入門二十

CountDownLatch(閉鎖)計數器   有一個任務A,它要等待其他4個任務執行完畢之後才執行,此時就可以利用CountDownLatch來實現這種功能 package com.cppdy; import java.util.concurrent.CountDownLatch

java線程快速入門二十

第一次 () trace for import else spl 自己的 arr CountDownLatch(閉鎖)計數器   有一個任務A,它要等待其他4個任務執行完畢之後才執行,此時就可以利用CountDownLatch來實現這種功能 package com.cp

JavaEE MyBatis關聯對映之教材學習筆記

在實際運用中,多對多也是十分常見的,比如一個訂單可能包含多個產品,而每個商品有可能出現在多個訂單中,在資料庫中這樣的情況就需要一張中間表來維護,下面通過一個案例來學習 1.新建三個資料表 其中訂單表在上一票部落格中已經建立過了(點這裡跳轉至上篇部落格),下面展示中間表以及商品表的建立

JavaEE MyBatis關聯對映之一教材學習筆記

在實際應用中,應用更多的是一對多,例如每一個使用者可以有多個訂單,在使用MyBatis中是怎樣處理一對多的關係呢,在MyBatis對映檔案中有一個resultMap元素,此元素包含一個<collection>子元素,MyBatis就是通過他來處理一對多關係的, 下面通過一個案例瞭

Python3基礎之三十 執行緒&程序

一、多執行緒 Threading 多執行緒 Threading 是一種讓程式擁有分身效果. 能同時處理多件事情. 一般的程式只能從上到下一行行執行程式碼, 不過多執行緒 (Threading)就能打破這

jQuery中的基本選擇器四、:* 、 . 、element(直接標籤名)、 或者用逗號隔開跟

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>基本選擇器</title> <meta http-equiv="content

機器學習二十——Optimizer, 單分類SVM&分類SVM, 時間序列分析

Optimizer 在《機器學習(一)》中,我們已經指出梯度下降是解決凸優化問題的一般方法。而如何更有效率的梯度下降,就是本節中Optimizer的責任了。 Momentum Momentum是梯度下降法中一種常用的加速技術。其公式為: vt

hibernate many to many

    package com.zking.pojo; import java.util.HashSet; import java.util.Set; public class Menu { private String mid; private St

老師and學生

ER teacher: 欄位名 主鍵 型別 描述 id pk int 老師編號 name varchar 老師姓名 student: 欄位名 主鍵 型別 描述 id pk int 學生編號 name varchar 學生姓名 中間表: tea

2017年校聯合訓練 第五場吉如

官方題解 1006 Rikka with Graph hdoj6090題目連結 貪心加邊 m<=n-1時,邊都從同一個點出發向不同的點連邊,呈菊花狀 中心點與其餘有邊的點的距離和:2*m

人臉二十--A Recurrent Encoder-Decoder Network for Sequential Face Alignment

轉自:https://blog.csdn.net/shuzfan/article/details/52438910 本次介紹一篇關於人臉關鍵點檢測(人臉對齊)的文章: 《ECCV16 A Recurrent Encoder-Decoder Network for Sequential Fac

Effective_STL 學習筆記二十 永遠讓比較函式相等的值返回 false

  除非比較函式總是為相等的值返回 false,否則將會打破所有的標準關聯容器, 不管關聯容器是否允許存在副本(set、map、multiset、multimap) 對於(set、map)使用 less_equal (<=): 1   !( 10A <= 10B ) &a

輸入棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列劍指offer

題目 輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。 分析: 在二叉搜尋樹中,每個結點都有兩個分別指向其左、右子樹的指標,左子樹結點的值總是小於父結點的值,右子樹結點的值總是大於父結點的值。在雙向連結串列中,每個結點