0

@OneToMany双向中,当EntityManger更新具有 的集合的 ProjectValue 时TaskEntityManger不能删除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应该支持这个功能吗?

4

2 回答 2

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
}
于 2012-09-26T14:36:59.773 回答
0

双向关联具有所有者方和反方。Hibernate 查看所有者方以了解是否存在关联。所有者方是没有mappedBy属性的一方。因此,在这种情况下,所有者方是 Task。

因此,如果要将任务 CCC 从其项目计划中分离出来,则必须将其projectPlan字段设置为空。如果要删除任务 CCC,则必须使用 删除它em.remove()

于 2012-09-21T08:06:52.627 回答