天天看點

JPA一對多,多對一雙向關聯

下面是一個訂單與訂單項的配置。

級聯操作與懶加載的配置在注釋裡面有詳細的描述。

訂單(Order):

@Entity
@Table(name="orders")
public class Order {
    
    @Id
    @Column(length=40)
    private String orderId;        //訂單ID
    
    @Column(nullable=false)
    private Float amount = 0f;    //總價
/* 
     * cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE}
     * 級聯重新整理:當擷取最新的訂單記錄時,是否擷取最新的訂單項記錄
     * 級聯儲存:當儲存Order的時候,需不需要對對Order下面的OrderItem進行儲存 
     * 級聯合并(更新):當Order處于遊離态的時候,如果更新Order時,items修改了,是否把OrderItem同步更新到資料庫
     * 級聯删除:當删除Order時,是否對Order裡面的所有OrderItem也執行删除操作(順序是:先删除訂單項,再删除訂單)
     * 
     * 注意:1隻用調用refresh()方法時,級聯重新整理才起作用
     *        隻有調用persist()方法時,級聯儲存才起作用
     *        隻用調用merge()方法時,級聯更新才起作用
     *        隻用調用delete()方法時,級聯删除才起作用
     *       2需要用到級聯重新整理的情形:當我們擷取到一條記錄後,在對這個記錄操作的時候,有人把這條記錄修改了,如果我們想拿到最新的資料,必須調用refresh()方法
     *        即使調用find()方法也擷取不到最新的資料,因為再次調用find()方法是,是從EntityManager的一級緩存中取資料。
     *        如:EntityManager em = factory.createEntityManager();
     *         Person person = em.find(Person.class,1)
     *         em.refresh();
     *         System.out.println(person);
     *     
     */
    
    /*
     * fetch=FetchType.EAGER    fetch=FetchType.LAZY
     * 如果希望擷取Order的時候,立即擷取OrderItem集合,用FetchType.EAGER
     * 如果希望擷取Order的時候,并不需要立即擷取OrderItem集合,隻有通路items屬性并對其操作的時候才擷取,用FetchType.LAZY
     * 
     * 注意: 1.通路延遲屬性時,EntityManger必須是打開狀态,否則會抛出延遲加載例外
     *     2.如果是得到多的一方,預設的是延遲加載,例如:OneToMany
     *       如果是得到一的一方,預設的是立即加載,例如:OneToOne,ManyToOne
     */
    
    /*
     * mappedBy申明了這個類為關系被維護端,指明了在關系維護端由哪一個屬性維護這個關系。
     * 相當于Hibernate中:
     * <set name="item" inverse=true>
     * </set>
     */
    @OneToMany(cascade={CascadeType.REFRESH,CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REMOVE},
            fetch=FetchType.LAZY,mappedBy="order")
    private Set<OrderItem> items = new HashSet<OrderItem>();
    
    public String getOrderId() {
        return orderId;
    }
    
    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }
    public Float getAmount() {
        return amount;
    }
    
    public void setAmount(Float amount) {
        this.amount = amount;
    }

    public Set<OrderItem> getItems() {
        return items;
    }

    public void setItems(Set<OrderItem> items) {
        this.items = items;
    }
           

訂單項(OrderItem):

@Entity
public class OrderItem {
	
	@Id
	@GeneratedValue	//ID自增長
	private Integer id;
	
	@Column(length=40,nullable=false)
	private String productName;

	@Column(nullable=false)
	private Float sellPrice;
	
	/*
	 * 級聯儲存:一般來說不需要,不可能儲存某一個訂單項的時候就儲存訂單
	 * 級聯更新:需要,如果改變了訂單項的價格,一般來說需要改變訂單的總價
	 * 級聯重新整理:當擷取訂單項的最新記錄時,是否需要擷取訂單的最新記錄
	 * 級聯删除:不需要
	 */
	
	/*
	 * 加載行為:預設是立即加載
	 */
	
	/*
	 * optional=true 表示可選,即外鍵字段可以為空
	 * optional=false 表示不可選,即外鍵字段不為空
	 */
	
	/*
	 * @JoinColumn(name="order_id")	資料庫中外鍵的名字為order_id
	 */
	@ManyToOne(cascade={CascadeType.MERGE,CascadeType.REFRESH},
			fetch=FetchType.EAGER,optional=false)
	@JoinColumn(name="order_id")
	private Order order;
	
	public Integer getId() {
		return id;
	}
	
	public void setId(Integer id) {
		this.id = id;
	}
	public String getProductName() {
		return productName;
	}
	
	public void setProductName(String productName) {
		this.productName = productName;
	}
	public Float getSellPrice() {
		return sellPrice;
	}
	
	public void setSellPrice(Float sellPrice) {
		this.sellPrice = sellPrice;
	}

	public Order getOrder() {
		return order;
	}

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