在ManyToOne关系中使用级联

3

在Hibernate实体中,使用CascadeManyToOne关联的两侧是否合适?为了让问题更具体化,假设有以下相关实体:

   public class Department
    {
    public long id;

    @OneToMany(mappedBy = "department", cascade=cascadeType.REMOVE)
    private Set<Employee> employees;
    }

    public class Employee{

    @GeneratedValue(strategy=GeneratedValue.identity)
    public longempid;

    @ManyToOne
    public Department department;
    }

在上述关系中,一个Department有多个Employees,因此在删除Department时强制删除Employees是合理的。我说得对吗?
然而,关系的所有者是Employee。因此我的问题是,在哪里放置cascadeType.PERSIST才是适当的和正确的选择。我可以根据特殊需求选择两侧中的一侧,或者也可以在两侧都放置它吗?如果我将其放在Department方面,那么以下代码是否也会保存Employees,考虑到Employee是关系的所有者
Employee e1 = new Employee();
Employee e2 = new Employee();
Department d = new Department();
d.getEmployees.add(e1);
d.getEmployees.add(e2);
em.persist(d);

我几乎确定,如果我在Employee端放置cascadeType.PERSIST,相反的情况也是适用的。(保存Employee将同时保存Department)。

1个回答

4

首先,在您发布的代码中,员工不是协会的所有者。如果该关联是双向的,并且如果OneToMany关联因此使用mappedBy属性定义,则会出现这种情况:

@OneToMany(mappedBy = "department", cascade = cascadeType.REMOVE)
private Set<Employee> employees;

(请注意,我还将该字段设置为私有。永远不应使用公共字段。)
关于删除部门:在我的公司中,当删除一个部门时,该部门的所有员工并不会自动被解雇。他们可以被分配到另一个部门,甚至可以在公司中待着而不被分配到任何一个部门,但他们不会被删除。我理解你的应用程序不一定模拟现实世界,但是不,当删除一个部门时强制删除员工并不一定合理。
现在,假设映射如上所述,是的,你可以完美地向OneToMany关联添加PERSIST级联。级联和所有权是正交的概念。如果你想从一个部门向它的员工(例如,如果你想在创建部门时创建员工)级联persist()操作,那么添加这个级联。为了保存关联,由于所有者方是Employee,employee.department字段必须正确初始化。

关于mappedBy,你是正确的,因此我已经更新了问题。从你的回答中,我推断出你的建议是,cascadeType.PERSIST可以在双方都使用并且有效。我是对的吗? - arjacsoh
我当然想尝试一下,但有些东西阻止我在我的电脑上使用Hibernate。请查看我对可能原因的相关回答:http://stackoverflow.com/questions/16638930/hibernate-does-not-create-table-in-the-database - arjacsoh
1
如果级联PERSIST在部门(而不是所有者)一侧,则通过执行department.getEmployees().add(new Employee()); session.persist(department)保存Employee,但它在外键Department_ID列上为null。显然,需要首先employee.setDepartment(department); - arjacsoh
是的,这就是我所说的“为了保存关联,由于所有者方是Employee,因此需要正确初始化employee.department字段”。 - JB Nizet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接