【问题标题】:Have JPA/Hibernate to replicate the "ON DELETE SET NULL" functionality让 JPA/Hibernate 复制“ON DELETE SET NULL”功能
【发布时间】:2012-04-14 04:58:27
【问题描述】:

我已经能够让 JPA/Hibernate 成功复制 ON DELETE CASCADE 功能(似乎是默认行为),但我现在正在尝试复制 ON DELETE SET NULL 功能,但我遇到了问题。

这是我的两个课程:

@Entity
@Table(name = "teacher")
public class Teacher
{
    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false, length = 4)
    private int id;

    @OneToMany(mappedBy = "teacher")
    private List<Student> studentList;

    // ...
}

@Entity
@Table(name = "student")
public class Student
{
    @Id
    @GeneratedValue
    @Column(name = "id", nullable = false, length = 4)
    private int id;

    @ManyToOne(optional = true)
    @JoinColumn(name = "teacher_id", nullable = true)
    private Teacher teacher;

    // ...
}

当我尝试删除教师时,出现以下错误:

org.springframework.dao.DataIntegrityViolationException: 无法执行 JDBC 批量更新; SQL [delete from teacher whereteacher_id=?];约束 [null]
...
原因:org.hibernate.exception.ConstraintViolationException:无法执行 JDBC 批量更新
...
原因:java.sql.BatchUpdateException:批量条目 0 从teacher_id='1'被中止的教师中删除。调用 getNextException 查看原因。

我做错了吗?是不是可以实现?

谢谢。

【问题讨论】:

  • 您想将该记录的所有列设置为 null 吗?或学生实体的所有字段
  • 我希望在将studentteacher 从系统中删除后,studentteacher 列变为null
  • 并不是说您想更改 JPA 的架构,但我很好奇将其更改为对连接表进行级联删除的 ManyToMany 的效果。它应该删除关联并离开学生。

标签: java hibernate jpa


【解决方案1】:

目前使用 jpa/hibernate 似乎不可能。

On delete set null in hibernate in @OneToMany

JBs 的解决方案看起来很干净:

for (Department child : parent.getChildren()) {
    child.setParentDepartment(null);
}
session.delete(parent);

您还应该能够将其放入 PreRemove:

@PreRemove
private void preRemove() {
    for (Student s : studentList) {
        s.setTeacher(null);
    }
}

【讨论】:

  • 谢谢,这两种解决方案都能完美运行。我个人更喜欢第二个:)
  • @PreRemove 解决方案不可移植。请参阅 JPA 规范第 3.5 节。 一般来说,可移植应用程序的生命周期方法不应该 [...] 修改同一持久性上下文中的关系。
  • 这行得通,但是当我从 'Teacher' 中删除 'Student' 并且我想将相同的 'Student' 添加到不同的 'Teacher' 时 - 它根本不起作用 - 'Student' 为 null DB中的“老师”。
【解决方案2】:

定义呢

@ForeignKey(name = "fk_student_teacher",
            foreignKeyDefinition = " /*FOREIGN KEY in sql that sets ON DELETE SET NULL*/")

?

【讨论】:

  • 这仅用于在模式生成生效时指定关联数据库中的外键约束。
  • 这不是数据库中立的,除了它是最好的方法,因为它清晰、合乎逻辑且快速。
【解决方案3】:

我认为最好的解决方案是设置删除操作的用户 SQL 语句如下:

CREATE TABLE table_name
(
  column1 datatype null/not null,
  column2 datatype null/not null,
  ...

  CONSTRAINT fk_column
     FOREIGN KEY (column1, column2, ... column_n)
     REFERENCES parent_table (column1, column2, ... column_n)
     ON DELETE SET NULL
);

当用户通过其他级联删除删除行时,您使用表引用对此已删除行,您无法使用休眠解决方案并返回 SQL 异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 1970-01-01
    相关资源
    最近更新 更多