[英]cascading delete in playframework-how to model the Entities
在使用play-1.2.4
創建在線商店應用程序時,我遇到了jpa的一些問題。我想在play中使用CRUD module
提供一個管理區域。這里,管理員用戶可以創建/編輯或刪除實體應用程序(如Customer
, Order
, Item
等)。
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)
界面列出了Customer
和Order
當選擇特定Customer
(創建Order
)並單擊刪除按鈕時,會導致JPA error
JPA error
A JPA error occurred (Cannot commit): collection owner not associated with session: models.Order.cartItems
這是堆棧跟蹤
如果有人能理解為什么會這樣,請告訴我。
有趣的是,我可以點擊特定Order
的delete 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.