休眠级联删除不按预期方式工作

问题描述:

我正在使用休眠3并试图删除数据库中的记录,并且删除不像我所期望的那样工作。该模式休眠正在对(在伪代码):休眠级联删除不按预期方式工作

create table Employer(
    employer_id number(12) primary key, 
    employer_name varchar2(50) 
); 

create table Employee(
    employee_id number(12) primary key, 
    employee_name varchar2(50), 
    employer_id number(12) foreign key references employer.employer_id not null 
); 

create table Employee_Roles(
    role_id number(12) primary key, 
    employee_id number(12) foreign key references employee.employee_id not null, 
    role varchar2(50) 
); 

我的冬眠类映射看起来像:

@Entity 
public class Employer{ 

    @Id 
    @Column(name = "EMPLOYER_ID") 
    private long id; 

    @Column 
    private String name; 


    @OneToMany(targetEntity = Employee.class, fetch = FetchType.EAGER) 
    @JoinColumn(name = "employer_id") 
    @Cascade(CascadeType.ALL) 
    private Set<Employee> employees; 
} 

@Entity 
public class Employee{ 

    @ManyToOne(targetEntity = Employer.class) 
    @JoinColumn(name = "employer_id") 
    @Cascade(value = CascadeType.SAVE_UPDATE) 
    private Employer employer; 

    @OneToMany(targetEntity = EmployeeRole.class, fetch = FetchType.EAGER) 
    @JoinColumn(name = "employee_id") 
    @Cascade(CascadeType.ALL) 
    private Set<Employee> employees; 
} 

@Entity 
public class EmployeeRole{ 

    @ManyToOne(targetEntity = Employee.class) 
    @JoinColumn(name = "employee_id") 
    @Cascade(value = CascadeType.SAVE_UPDATE) 
    private Employee employee; 
} 

现在有了这个配置,我呼吁:

getCurrentSession().delete(someEmployerEntity); 

是什么发生是:

Hibernate: update EMPLOYEE set EMPLOYEE_ID=null where EMPLOYEE_ID=? 
Hibernate: update EMPLOYEE_ROLE set employee_id=null where employee_id==? 
[2011-04-15 15:59:53,487] JDBCExceptionReporter WARN - SQL Error: -10, SQLState: 23502 
[2011-04-15 15:59:53,487] JDBCExceptionReporter ERROR - integrity constraint violation: NOT NULL check constraint; SYS_CT_10058 table: EMPLOYEE_ROLE 

并引发异常。由于session.remove(..)调用,我期望的是要删除的雇主记录,以及与雇主相关的所有员工记录以及与删除的员工记录关联的所有EmployeeRole记录。这是一个正确的假设吗?或者我误解了这里的一个关键概念?

+1

您可能需要查看delete-all-orphan并查看inverse = true。反向通常会首先删除外键值(避免'违反完整性约束'),然后删除父值 – hooknc 2011-04-15 21:12:45

Cascade all-delete-orphan应该可以解决你的问题。但是,它是Hibernate的一部分,而不是EJB标准。如果你想这样做,而不是被困在供应商的解决方案中,我建议你看看this article

祝你好运!

编辑:遵循您的建议我将'mappedBy'属性添加到@OneToMany注释中,似乎是使用inverse =“true”来指定拥有关系的注释方式。相关的变化部分的关系如下所示:

public class Employee{ 

    @OneToMany(targetEntity = EmployeeRole.class, mappedBy="employee", fetch = FetchType.EAGER, cascadeType=CascadeType.ALL) 
    private Set<EmployeeRole> employeeRoles; 
} 


public class Employer{ 

    @OneToMany(targetEntity = Employee.class, mappedBy="employer", fetch = FetchType.EAGER, cascadeType=CascadeType.ALL) 
    private Set<Employee> employees; 
} 
+2

按照您的建议,我找到了解决方案,因为它与关系所有者有关。未来的任何人都在想它是什么样的 – BuffaloBuffalo 2011-04-18 14:10:00