2016-05-12 88 views
0

我有三個實體,會話,訂單和用戶(我的在線電影票項目的一部分)。在我的域模型中,Order保留用戶和會話的fk。正如你可以在我的代碼中看到:Jpa幾個@ManyToOne與級聯


@Table(name="Orders") 
@Entity 

public class Order { 
    @ManyToOne 
    @JoinColumn(nullable = false) 
    private User user; 

    @ManyToOne 
    private Session session; 
    ... 
} 



@Entity 
@Table(name="Session") 

public class Session { 
    @OneToMany(fetch=FetchType.LAZY, 
       cascade = CascadeType.ALL, 
       mappedBy = "session") 
    private List<Order> orders = new ArrayList<Order>(); 
    ... 
} 



@Table(name="User") 
@Entity 

public class User { 
    @OneToMany(cascade = { CascadeType.PERSIST, 
          CascadeType.MERGE, 
          CascadeType.REMOVE }, 
       mappedBy = "user") 
    private @Getter Set<Order> orders = new HashSet<>(); 
    ... 
} 

我的問題是,我可以使用CascadeType.ALL兩個會話和用戶? 使用會話和用戶更新訂單時是否存在潛在的衝突?


正如您所見,我使用fetchType.Lazy,它可以保證Session和User中的訂單都是最新的嗎?

回答

0

問題1:這是一個很好的問題,但爲了回答它,您需要了解owning實體的概念。帶有@ManyToOne註釋的Entity是關係的所有者。這對於開發者來說很重要,因爲如果沒有關係,它就不會持續存在,在這種情況下,這意味着設置Order.user。不過,既然你對非所屬Usercascade註解,你必須做額外的工作來使用級聯功能:

// create Order 
Order order = new Order(); 
// create User and Set of orders 
User user = new User(); 
Set<Order> userOrders = new HashSet<Order>(); 
user.setOrders(userOrders); 
userOrders.add(order); 
// and set Order.user 
order.setUser(user); 
// persist with cascade 
em.persist(user); 

請注意,您必須創建一個集訂單以及設置Order.user堅持與級聯。但是,如果你把cascade註釋上擁有實體Order,那麼你的工作變得簡單多了:

// create User 
User user = new User(); 
// create Order 
Order order = new Order(); 
// and set Order.user 
order.setUser(user); 
// persist with cascade 
em.persist(order); 

現在,只要堅持order將持續新UserOrder一個電話。如果Order實體上沒有cascade註釋,在User之前持續Order會給您一個例外。

參考文獻:What is the 「owning side」 in an ORM mapping?In a bidirectional JPA OneToMany/ManyToOne association, what is meant by 「the inverse side of the association」?

問題2:FetchType.LAZY意味着你必須通過特定的查詢要求獲得孩子們,所以如果我明白你的問題,答案是否定的,它並不能保證任何事情。使用FetchType.LAZY當你得到Session時,當實體變爲分離時,通常在你離開會話Bean或服務層後,你將無法訪問Session.orders。如果您需要訪問的訂單,你需要讓他們在選擇查詢:

「從的Session選擇不同我們攜手取s.orders」

編輯:如前所述,在默認情況下這個查詢會執行一個sql「內部連接」,如果沒有命令,它將不會返回任何內容。相反,做

「選擇會話的左明顯我們攜手取s.orders」

,讓您始終獲得了在數據庫中的會話。

參考:Difference between FetchType LAZY and EAGER in Java Persistence API?

+0

謝謝,就是我在找什麼! – ivy

+0

「從Session s join fetch s.orders中選擇不同的s」,但如果s.orders爲空,則此查詢將返回null。如果我的數據庫中已經有一個空訂單的會話,我如何向其中插入訂單? – ivy

+0

@常春藤,請看更新。 –