以正确的方式删除实体和关系(JPA)
问题描述:
我有一个实体Task和一个道具:TaskDao。任务实体具有到类别的ManyToOne映射。当我删除任务,我还需要从集合中删除的任务类别:以正确的方式删除实体和关系(JPA)
// remove() method in TaskDao
public void remove (Task p_task) {
// p_task is Detached, p_task.getCategory() is Detached
p_task = em.merge(p_task);
// p_task is Attached, p_task.getCategory() is Attached
em.remove(p_task);
// p_task is Detached, p_task.getCategory() is Attached
p_task.getCategory().removeTask(p_task);
}
评论表明(在这一点),如果P_TASK和/或p_task.category的安装/拆卸。首先让我解释一下为什么我选择这个顺序。首先,我需要合并p_task,以便p_task.category被附加,并且为了移除它需要合并的p_task。因为em.remove(p_task)可以抛出ConstraintException,所以p_task从类别集合中被移除,这种情况下不应该从类别集合中删除该任务。
这是正确的认同?另外,在em.remove(p_task)之后,我仍然感到惊讶,p_task.category仍然存在。
编辑:我应该从实体类中提供一些代码。
public class Task implements Serializable {
@JoinColumn(name = "category_id", referencedColumnName = "id")
@ManyToOne(cascade = CascadeType.MERGE, optional = false)
private Category category;
}
public class Category implements Serializable {
@OneToMany(cascade = CascadeType.MERGE, mappedBy = "category")
private List<Task> taskCollection;
public void addTask (Task p_task) {
if (taskCollection == null) {
taskCollection = new ArrayList<>();
}
if (!taskCollection.contains(p_task)) {
taskCollection.add(p_task);
}
}
public void removeTask (Task p_task) {
taskCollection.remove(p_task);
}
}
在下面的代码P_TASK从category.taskCollection去除,而事务回滚:
// remove() method in TaskDao
public void remove (Task p_task) {
p_task = em.merge(p_task);
p_task.getCategory().removeTask(p_task); // will not be rolled back if em.remove(p_task) throws an exception
em.remove(p_task);
}
答
这是确定的,据我所知。但是,您有一些不正确的假设:
- em.remove(p_task)不会抛出ConstraintException。清除od将被删除。如果抛出此异常,唯一要做的就是回滚事务并关闭实体管理器,因为它会使其处于不一致的状态。因此,在从类别中删除任务之前或之后删除任务并没有太大的区别。
- 您删除任务,但不删除该类别。那为什么这个类别还没有被附加?
答
它是正确的答案。您必须从集合中删除任务以确保集合的功能。
也许检查P_TASK被合并前,如果真的任务分离Ç
1.但p_task.getCategory()。removeTask(P_TASK)语句不会回滚,对不对?这会在数据库和内存数据之间留下不一致。 2.当我删除任务时,我不想删除关联的类别。我确实希望从category.taskCollection中删除已删除的任务。 – BigJ
如果回滚事务,则在事务期间完成的每个修改都会回滚。如果关闭会话,它在内存中保存的每个实体都会被分离,并且必须被视为不一致。你必须忘掉它们。 –
我使用CMT,所以我自己实际上并不控制事务。你会建议在调用em.remove()之前删除内存中的引用吗? – BigJ