2012-03-05 45 views
5

在使用play-1.2.4創建在線商店應用程序時,我遇到了一些jpa問題..我想提供一個使用CRUD module的管理區域。在這裏,管理員用戶可以創建/編輯或刪除應用程序中的實體(如Customer s,Order s,Item s等)。在playframework中級聯刪除 - 如何爲實體建模

一個Customer可以創建Orders.Each Order將有一組CartItem s.When的Order被刪除的,相應的CartItem s必須是一個deleted.When Customer被刪除,他的所有訂單必須被刪除well.I我認爲我可以通過在jpa註釋中設置cascade屬性來獲得此信息。

我模仿它像這樣

Customer.java

@Entity 
public class Customer extends Model { 
    @Email 
    @Required 
    public String email; 
    ... 
    @OneToMany(mappedBy="customer", cascade=CascadeType.ALL) 
    public List<Order> orders; 
    @OneToOne 
    public PayMethod currentPayment; 
    ... 
} 

Order.java

@Entity 
public class Order extends Model { 
    @OneToMany(cascade=CascadeType.ALL,orphanRemoval=true,fetch=FetchType.EAGER) 
    public Set<CartItem> cartItems; 

    @ManyToOne 
    public Customer customer; 
    @ManyToOne 
    public PayMethod paymentMethod; 
    ... 
} 

CartItem.java

@Entity 
public class CartItem extends Model implements Comparable<CartItem>{  
    @ManyToOne 
    public Item item; 
    public int quantity; 
} 

PayMethod.java

@Entity 
public class PayMethod extends Model { 
    @Required 
    public String cardNumber; 
    @ManyToOne 
    public Customer customer; 
    ... 
} 

下創建了數據庫表

客戶表

id | email  | fullname | currentpayment_id 
---|-------------|---------------|----------------- 
2 |[email protected]| jon   |29 

順序表

id |customer_id | paymentmethod_id 
----+------------+----------------- 
25 | 2   |  29 

cartitem表

id | quantity | item_id 
----+----------+--------- 
26 |  1 |  14 

* order_cartitem表*

order_id | cartitems_id 
----------+-------------- 
     25 |   26 

在使用CRUD創建管理界面(我沒有任何implented方法,只是使用提供CRUD模塊是),我試圖刪除一個客戶,但後來,我得到這個錯誤,

ERROR: update or delete on table "cartitem" violates foreign key constraint "fk7ff437ad3e28aa91" on table "order_cartitem" 
Detail: Key (id)=(26) is still referenced from table "order_cartitem". 
08:03:03,031 ERROR ~ Could not synchronize database state with session 

模型化實體的方式有什麼問題嗎?我認爲Customer上的刪除將被級聯到Order,而這又會級聯到它的CartItem

我該怎麼做才能獲得這種級聯效應?或者我必須手動刪除每個包含的實例CartItem s?

編輯:按勒布的答覆

class Order extends Model { 
    @OneToMany(mappedBy="order", cascade=CascadeType.ALL,orphanRemoval=true,fetch=FetchType.EAGER) 
    public Set<CartItem> cartItems; 
    ... 
} 

class CartItem extends Model implements Comparable<CartItem>{ 

    @ManyToOne 
    public Item item; 

    public int quantity; 

    @ManyToOne 
    public Order order; 
... 
} 

static void addItemToCart(Long itemId,Long orderId,String quantity) { 
    Item item = Item.findById(itemId); 
    Order order = Order.findById(orderId); 
    int qty = Integer.parseInt(quantity); 
    CartItem cartItem = new CartItem(item,qty); 
    cartItem.order=order; 
    order.addItem(cartItem, qty); 
    order.save(); 
... 
} 

這擺脫order_cartitem表,並增加了一個現場ORDER_IDcartitem表

cartitem表

 id | quantity | item_id | order_id 
    ----+----------+---------+---------- 
    26 |  1 |  14 |  25  
    27 |  1 |  20 |  25 

admin(CRUD)界面,列出了Customer S和Order s.When特定Customer(誰創造了Order一)選擇和刪除按鈕被點擊,它會導致JPA error

JPA error 
A JPA error occurred (Cannot commit): collection owner not associated with session: models.Order.cartItems 

這裏是stacktrace

如果有人可以理解爲什麼發生這種情況,請告訴我。

有趣的是,我可以點擊delete button特定Order,併成功調用下面的控制器方法,

Admin.java

public static void deleteOrder(Long id) { 
    Order order = Order.findById(id); 
    order.delete();  
    ... 
} 

其刪除Order和所有其CartItem s成功.. 那麼,爲什麼在刪除Customer時不會發生這種情況?

+1

代碼看起來對我很好。也許這個線程有點幫助找到問題的原因:http://stackoverflow.com/questions/2011519/jpa-onetomany-not-deleting-child – Bjarne77 2012-03-05 08:59:07

+0

感謝偉大的鏈接..將通過它 – 2012-03-05 09:16:36

回答

2

加給你的cartitem類

@ManyToOne 
public Order order; 

,並在您cartItems一個的mappedBy = 「訂單」 讓你們的關係bidirectionnal @OneToMany

Hibernate就會更好地處理您的刪除。我猜測,沒有這個雙向鏈接,hibernate試圖首先將列設置爲null。您還可以嘗試允許連接表中的空值查看如果不想啓用雙向關係會發生什麼情況

+0

謝謝你的答覆..我試過這個,現在,當我試圖刪除一個客戶通過CRUD(管理員),我得到這個錯誤:錯誤〜一個斷言失敗發生(這可能表明在Hibernate中的錯誤,但更可能是由於不安全使用會話) org.hibernate.AssertionFailure:集合所有者未與會話相關聯:models.Order.cartItems – 2012-03-05 10:18:19

+0

這裏是[stacktrace] [1] [1]:http://pastebin.com/r42mPEdB – 2012-03-05 10:23:54

+0

我有更新了有問題的代碼(接近尾聲) – 2012-03-05 10:33:03

0

JPA級聯屬性存在問題。嘗試從休眠中使用相關的級聯註釋,並從JPA中刪除所有使用的級聯。以下是您的PayMethod模型類的示例:

// Be careful, import the realted annotations from hibernate (not JPA) 
import org.hibernate.annotations.OnDelete; 
import org.hibernate.annotations.OnDeleteAction; 

@Entity 
public class PayMethod extends Model { 
    @Required 
    public String cardNumber; 

    @ManyToOne 
    @OnDelete(action = OnDeleteAction.CASCADE) 
    public Customer customer; 
    ... 
} 

上述方法適用於單向映射。我希望這能解決你的問題。

0

我有一個類似的問題,但我沒有使用List,我使用的是實體的數組。

我的包裝實體的問題是它沒有初始化數組(新MyEntity [0]),正如我通常對我的列表(新ArrayList(0))所做的那樣。

我意識到(經驗方法),當試圖通過「全部刪除孤立」關係調用「合併」到一個「空」數組時,「org.hibernate.AssertionFailure:collection owner與會話沒有關聯:「出現了。

所以我的建議是:當使用「全部刪除孤兒」關係時,用一個空實例初始化您的集合(包含數組)。