我得到了一个Deal
,它可以有多个DealItems
。
DealItems
在 Deal
中使用以下 JPA 注释进行链接:
public class DealEntity extends BasicEntity {
@OneToMany(mappedBy = "deal", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<DealItemEntity> items;
...
这是 DealItem
内的关系:
public class DealItemEntity extends BasicEntity {
@ManyToOne
@JoinColumn(name = "deal_id", nullable = false)
private DealEntity deal;
...
当我删除 DealItem
时,它会被删除并再次保留,当我在删除后访问 Deal
时,请参见此处:
public FullDealResponse deleteDealItem(final String dealCode, final long dealItemId) {
DealEntity dealEntity = dealControl.findDealByDealCode(dealCode);
if (dealEntity == null) {
throw new WorkbenchGenericErrorException("Deal not found");
}
DealItemEntity dealItemEntity = dealItemControl.findDealItemByIdAndDealId(dealItemId, dealEntity.getId());
if (dealItemEntity == null) {
throw new WorkbenchGenericErrorException("Deal item not found");
}
// this makes a database DELETE call that is executed after the session is done
dealItemControl.deleteDealItem(dealItemEntity);
// When I remove this and I do not return anything, the deletion works
return this.getFullDealResponse(dealEntity);
}
编辑:
这是 getFullDealResponse()
和 getFullDealItemResponse()
:
private FullDealResponse getFullDealResponse(final DealEntity dealEntity) {
FullDealResponse response = new FullDealResponse();
response.setDescription(dealEntity.getDescription());
response.setTitle(dealEntity.getTitle());
response.setDealCode(dealEntity.getDealCode());
response.setCreatedAt(dealEntity.getCreatedAt());
response.setUpdatedAt(dealEntity.getUpdatedAt());
// get related items
List<FullDealItemResponse> itemsResponse = new ArrayList<FullDealItemResponse>();
for (DealItemEntity dealItemEntity : dealEntity.getItems()) {
itemsResponse.add(this.getFullDealItemResponse(dealItemEntity));
}
response.setItems(itemsResponse);
return response;
}
private FullDealItemResponse getFullDealItemResponse(final DealItemEntity dealItemEntity) {
FullDealItemResponse response = new FullDealItemResponse();
response.setId(dealItemEntity.getId());
response.setDescription(dealItemEntity.getDescription());
response.setTitle(dealItemEntity.getTitle());
response.setCreatedAt(dealItemEntity.getCreatedAt());
response.setUpdatedAt(dealItemEntity.getUpdatedAt());
return response;
}
这是deleteDealItem()
和delete()
函数:
public void deleteDealItem(final DealItemEntity dealItemEntity) {
super.delete(DealItemEntity.class, dealItemEntity.getId());
}
protected void delete(final Class<?> type, final Object id) {
Object ref = this.em.getReference(type, id);
this.em.remove(ref);
}
当我切换CascadeType
时可以解决这个问题吗?如果可以,哪种类型是正确的?或者我是否必须迭代 Deal.getItems()
,删除不需要的项目,使用 Deal.setItems()
设置新列表并仅更新 Deal
所以它会传播删除?
执行此操作的首选方法是什么?
最佳答案
I have replicated this code locally and verified my explanation
摘要:
级联没有影响。即使你去掉你的级联操作,单独保存每个项目,那么当你来到这个方法时,它也不会删除你的项目。
无论
deal.getItems
如何,都具有相同的行为初始化时,您必须删除dealItem
将其从deal.getItems
中删除除了直接删除 dealItem 之外。在双向关系中,您必须明确管理双方。完全相同的方式,您将 dealItem 添加到 deal 并在保存之前设置 dealItem 的 deal 字段。
总体说明
JPA 只能拥有与其 session 关联的特定项目的一种表示形式。
它是提供重复读取、脏检查等功能的基础。
JPA 还跟踪与其 session 关联的每个对象,如果任何跟踪的对象发生更改,它们将在事务提交时刷新。
仅当
deal
时对象(带有惰性deaItems
集合)和直接获取的dealItem
是与 session 关联的唯一两个实体,那么 JPA 在 session 中为每个实体都有一个演示文稿,因为不存在冲突,所以当您删除它时,它会通过dealItemControl.deleteDealItem
删除它。 dealItem 已删除但是,一旦您调用
deal.getItems
,JPA 不仅管理交易,还管理与deal
关联的每个交易项目。目的。所以当你删除dealItemControl.deleteDealItem
时,JPA 有一个问题,因为 deal.getItems 告诉它没有标记为删除。所以删除没有发出。
引用:生成的JPA QL也证实了我的解释
<强>1。与deal.getItems
和生成的查询
@OneToMany(mappedBy = "deal", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<DealItemEntity> items;
DealEntity dealEntity = dealControl.findDealByDealCode(dealCode);
....
dealItemControl.deleteDealItem(dealItemEntity);
....
dealEntity.getItems()
select deal0_.* from deal deal0_ where deal0_.id=?
select dealitem0_.*
deal1_.*
from
deal_item dealitem0_ inner join deal deal1_ on dealitem0_.deal_id=deal1_.id
where
dealitem0_.id=?
select items0_.* from deal_item items0_ where items0_.deal_id=?
<强>2。没有deal.getItems
和生成的查询
@OneToMany(mappedBy = "deal", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<DealItemEntity> items;
DealEntity dealEntity = dealControl.findDealByDealCode(dealCode);
....
dealItemControl.deleteDealItem(dealItemEntity);
select deal0_.* from deal deal0_ where deal0_.id=?
select dealitem0_.*
deal1_.*
from
deal_item dealitem0_ inner join deal deal1_ on dealitem0_.deal_id=deal1_.id
where
dealitem0_.id=?
delete from deal_item where id=?
关于java - JPA + @OneToMany + 删除 : Item is not deleted if I access parent later,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62498503/