簡體   English   中英

在playframework中級聯刪除 - 如何為實體建模

[英]cascading delete in playframework-how to model the Entities

在使用play-1.2.4創建在線商店應用程序時,我遇到了jpa的一些問題。我想在play中使用CRUD module提供一個管理區域。這里,管理員用戶可以創建/編輯或刪除實體應用程序(如CustomerOrderItem等)。

Customer可以創建Order每個Order都有一套CartItem s。當Order被刪除時,必須刪除相應的CartItem 。當Customer被刪除時,他的所有訂單也必須刪除。我想我可以得到這可以通過在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  |jon@gmail.com| 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創建的Admin界面中(我沒有實現任何方法,只是按原樣使用提供的CRUD模塊),我試圖刪除一個Customer,但是,我得到了這個錯誤,

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實例?

編輯:根據Seb的回復

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_id添加到cartitem表

cartitem表

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

admin(CRUD)界面列出了CustomerOrder當選擇特定Customer (創建Order )並單擊刪除按鈕時,會導致JPA error

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

這是堆棧跟蹤

如果有人能理解為什么會這樣,請告訴我。

有趣的是,我可以點擊特定Orderdelete button ,並成功調用以下控制器方法,

Admin.java

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

這會成功刪除Order及其所有CartItem ..那么,為什么刪除Customer時不會發生這種情況?

通過將此關系添加到您的cartitem類,使您的關系雙向

@ManyToOne
public Order order;

和cartItems @OneToMany中的mappedBy =“order”

那么hibernate將更好地處理你的刪除。 我猜測,沒有這個雙向鏈接,hibernate試圖首先將列設置為null。 您還可以嘗試在連接表中允許空值,以查看如果您不想啟用雙向關系會發生什么

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

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

我意識到(經驗方法)當試圖將“merge”調用到由“all-delete-orphan”關系關聯的“null”數組時,“org.hibernate.AssertionFailure:集合所有者與session:無關聯”出現了。

所以我的建議是:當使用“all-delete-orphans”關系時,用空實例初始化你的集合(包括數組)。

JPA的級聯屬性存在問題。 嘗試使用來自hibernate的相關級聯注釋,並刪除從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;
    ...
}

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM