在@OneToMany
双向,EntityManger
更新具有Task
集合的ProjectValue时,
EntityManger
无法删除内存中程序删除的子Task
。
是否会使用其他功能删除Task
?
DataStructure :
In ProjectPlan Table :
PRPJ0001, First Poject
In Task Table :
AAA, AAA, PRPJ0001
BBB, BBB, PRPJ0001
CCC, CCC, PRPJ0001
In Memory :
PRPJ0001, First Poject
AAA, AAA, PRPJ0001 --> No Changes
BBB, Change Name, PRPJ0001 --> Need to update
--> Need to delete CCC
NEW, NEW, PRPJ0001 --> Need to add
Problem : Entity Manger cannot delete CCC;
@Entity
public class ProjectPlan {
@Id
private String id;
private String name;
@OneToMany(mappedBy = "projectPlan", targetEntity = Task.class, cascade = {CascadeType.ALL})
private List<Task> taskList;
public ProjectPlan(){}
public ProjectPlan(String id, String name, List<Task> taskList) {
this.id = id;
this.name = name;
this.taskList = taskList;
}
//getter & setter
}
@Entity
public class Task {
@Id
private String id;
private String name;
@ManyToOne(targetEntity = ProjectPlan.class, cascade = {CascadeType.REFRESH})
@JoinColumn(name = "projectId", referencedColumnName = "ID")
private ProjectPlan projectPlan;
public Task(){
}
public Task(String id, String name, ProjectPlan projPlan) {
this.id = id;
this.name = name;
this.projectPlan = projPlan;
}
// getter & setter
}
public class Test {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
EntityManager em = emf.createEntityManager();
/*
Existing Data in Database
List<Task> taskList = new ArrayList<Task>();
ProjectPlan plan = new ProjectPlan("PRPJ0001", "First Poject", taskList);
Task task1 = new Task("AAA","AAA", plan);
Task task2 = new Task("BBB","BBB", plan);
Task task3 = new Task("CCC","CCC", plan);
taskList.add(task1);
taskList.add(task2);
taskList.add(task3);
*/
em.getTransaction().begin();
List<Task> taskList = new ArrayList<Task>();
ProjectPlan plan = em.find(ProjectPlan.class, "PRPJ0001");
/*Task "AAA" no changes*/
Task task1 = new Task("AAA","AAA", plan);
/*Task "BBB" updated info*/
Task task2 = new Task("BBB","Change Name", plan);
/*Task "CCC" removed*/
/*Task "NEW" newly created*/
Task task3 = new Task("NEW","NEW", plan);
taskList.add(task1);
taskList.add(task2);
taskList.add(task3);
plan.setTaskList(taskList);
em.merge(plan);
em.getTransaction().commit();
em.close();
}
}
如果Task
有另一个Sub Task List instance
(递归关系),Task
也将面临这种情况。我必须检查并检索需要实际删除的任务吗?您认为JPA
应支持此功能吗?
答案 0 :(得分:1)
在注释OneToMany上使用属性 orphanRemoval 。
<强>解释强>
当从关系中删除一对一或一对多关系中的目标实体时,通常需要将删除操作级联到目标实体。此类目标实体被视为“孤儿”,orphanRemoval属性可用于指定应删除孤立实体。
@Entity
public class ProjectPlan {
@Id
private String id;
private String name;
@OneToMany(mappedBy = "projectPlan", cascade = {CascadeType.ALL}, orphanRemoval=true) // --> new attribute
private List<Task> taskList;
public ProjectPlan(){}
public ProjectPlan(String id, String name, List<Task> taskList) {
this.id = id;
this.name = name;
this.taskList = taskList;
}
//getter & setter
}
@Entity
public class Task {
@Id
private String id;
private String name;
@ManyToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = "projectId", referencedColumnName = "ID")
private ProjectPlan projectPlan;
public Task(){
}
public Task(String id, String name, ProjectPlan projPlan) {
this.id = id;
this.name = name;
this.projectPlan = projPlan;
}
// getter & setter
}
答案 1 :(得分:0)
双向关联具有所有者方和反方。 Hibernate查看所有者方以了解是否存在关联。所有者方是不具有mappedBy
属性的方。因此,在这种情况下,所有者方是任务。
因此,如果要将任务CCC与其项目计划分离,则必须将其projectPlan
字段设置为null。如果要删除任务CCC,则必须使用em.remove()
删除它。