级联删除关系而不级联删除目标

Pet*_*der 7 java many-to-many hibernate reverse-engineering

Student_Teacher-table(Entityless)中,我在学生和教师之间有一个ManyToMany关系.

Student:       Teacher(owning-side):   Student_Teacher
1= Tim         50= Mrs. Foo            1=   1   50
2= Ann         51= Mr. Bar             2=   1   51
                                       3=   2   50
                                       4=   2   51
Run Code Online (Sandbox Code Playgroud)

如上所述,每个学生目前都与每位教师有关.

现在我想删除Ann,我喜欢使用数据库的级联技术从-table中删除条目,Student_Teacher但我既不想删除其他学生,也不想删除教师,也不想删除其他关系.

这就是我在学生实体中所拥有的:

@ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers() {
    return teachers;
}
Run Code Online (Sandbox Code Playgroud)

这就是我在教师实体中所拥有的:

@ManyToMany
@JoinTable(name="Student_Teacher", joinColumns = {
    @JoinColumn(name="StudentID", referencedColumnName = "TeacherID", nullable = false)
}, inverseJoinColumns = {
    @JoinColumn(name="TeacherID", referencedColumnName = "StudentID", nullable = false)
})
public Set<Student> getStudents() {
    return students;
}
Run Code Online (Sandbox Code Playgroud)

现在我想使用数据库的delete cascade功能.我再说一遍:数据库的删除级联功能仅针对Student_Teacher表!

问题:

org.h2.jdbc.JdbcSQLException: Referentielle Integrität verletzt: "FK_43PMYXR2NU005M2VNEB99VX0X: PUBLIC.Student_Teacher FOREIGN KEY(StudentID) REFERENCES PUBLIC.Student(StudentID) (2)"
Referential integrity constraint violation: "FK_43PMYXR2NU005M2VNEB99VX0X: PUBLIC.Student_Teacher FOREIGN KEY(StudentID) REFERENCES PUBLIC.Student(StudentID) (2)"; SQL statement:
delete from "Student" where name='Ann'
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345)
    at org.h2.message.DbException.get(DbException.java:179)
    at org.h2.message.DbException.get(DbException.java:155)
    at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:425)
Run Code Online (Sandbox Code Playgroud)

我不能用的是

@ManyToMany(cascade={CascadeType.REMOVE})
Run Code Online (Sandbox Code Playgroud)

因为文件告诉我:

(可选)必须级联到关联目标的操作.

"目标"是教师,所以这个级联将删除教师(我不想删除).

题:

如何配置实体以仅使用数据库的级联功能删除Ann和关系?

概念证明:

我尝试了另一个功能,我注意到有可能像这样配置外键:

@ManyToMany(cascade = { CascadeType.REMOVE })
@JoinTable(name="Student_Teacher", joinColumns = {
    @JoinColumn(name="StudentID", referencedColumnName = "TeacherID", nullable = false, foreignKey=@ForeignKey(foreignKeyDefinition="FOREIGN KEY (StudentID) REFERENCES Student ON DELETE NO ACTION"))
}, inverseJoinColumns = {
    @JoinColumn(name="TeacherID", referencedColumnName = "StudentID", nullable = false, foreignKey=@ForeignKey(foreignKeyDefinition="FOREIGN KEY (TeacherID) REFERENCES Teacher ON DELETE NO ACTION"))
})
public Set<Student> getStudents() {
    return students;
}
Run Code Online (Sandbox Code Playgroud)

问题是:这工作正常,但触发删除条目Student_Teacher我必须@ManyToMany(cascade = { CascadeType.REMOVE })在两侧指定.Hibernate不解析它foreignKeyDefinition,只看到CascadeType.REMOVE并将目标实体(和引用的Student Tim)从缓存中删除,但它们仍然在数据库中!因此,我必须在重新阅读教师夫人Foo和Bar先生以及学生蒂姆的存在后,清除hibernate会话.

Dra*_*vic 5

现在我喜欢使用数据库的删除级联功能.我再说一遍:数据库的删除级联功能仅针对Student_Teacher表!

只需在数据库模式级别定义级联删除,数据库就会自动执行.但是,如果在同一个持久化上下文实例中加载/操作关联的拥有方,那么持久化上下文显然会处于不一致状态,从而导致管理拥有方时出现问题,因为Hibernate无法知道后面做了什么它的背面.如果启用了二级缓存,事情会变得更加复杂.

所以你可以这样做,并注意不要Teacher在同一个会话中加载s,但我不建议这样做,我只写这个问题的答案.

如何配置实体以仅使用数据库的级联功能删除Ann和关系?

在JPA/Hibernate级别上没有这样的配置.映射中的大多数DDL声明仅用于自动模式生成,并且在涉及实体实例生命周期和关联管理时会被忽略.

我不能用的是

@ManyToMany(cascade={CascadeType.REMOVE})

实体生命周期操作和关联管理的级联是两个完全独立的概念.在这里你考虑前者,而你需要后者.

您面临的问题是,当您是拥有方时,您希望打破与Student(标记为的反面mappedBy)的关联Teacher.您可以通过从与其相关联的所有教师中删除学生来完成此操作,但这可能会导致加载大量数据(所有相关教师与所有学生一起).这就是为什么为关联表引入一个单独的实体可能是一个很好的折衷,正如@Mark已经提出的那样,正如我在以前的一些关于类似主题的回答以及其他一些潜在的改进中所建议的那样.

  • 这就是为什么我会放弃数据库级别的级联并使用替代方案. (3认同)