У меня есть сущность Task и дао для нее: TaskDao. Объект Task имеет сопоставление ManyToOne с категорией. Когда я удаляю задачу, мне также нужно удалить задачу из коллекции в категории:
// 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, его необходимо объединить. P_task удаляется из коллекции категорий в конце, потому что em.remove (p_task) может вызвать ConstraintException, в этом случае задача не должна быть удалена из коллекции категорий.
Это правильный подход? Кроме того, я был удивлен, что после 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);
}