简体   繁体   English

JPA Hibernate @ManyToOne 外键约束失败

[英]JPA Hibernate @ManyToOne foreign key constraint fails

I am working on a basic example to test cascade delete operation but I am getting exception.我正在研究一个基本示例来测试级联删除操作,但出现异常。 Here is my entities这是我的实体

@Table(name = "project")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Project implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "project_name")
    private String projectName;

    @ManyToOne(cascade = CascadeType.REMOVE)
    private Student student;

    ...
} 

and

@Entity
@Table(name = "student")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;
 
    ...
}

I already have one student data and one project related to it, and my expectation is when I delete student data, that project will automatically be deleted.我已经有一个学生数据和一个与之相关的项目,我的期望是当我删除学生数据时,该项目将自动删除。 But when I delete student data, I got an error但是当我删除学生数据时,出现错误

Caused by: java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`document_control`.`project`, CONSTRAINT `FKjvi932wdxw4ux6m7u6abiy7qv` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`))

I'm using JPA to delete the data, and here is my controller class我正在使用 JPA 删除数据,这是我的 controller class

@DeleteMapping("/students/{id}")
    public ResponseEntity<Void> deleteStudent(@PathVariable Long id) {
        log.debug("REST request to delete Student : {}", id);
        studentRepository.deleteById(id);
        return ResponseEntity
            .noContent()
            .headers(HeaderUtil.createEntityDeletionAlert(applicationName, false,
                ENTITY_NAME, id.toString()))
            .build();
    }

Am I missing something here?我在这里错过了什么吗?

The problem resides in that the foreign key from Project to Student is missing the option: "on delete cascade" ... such option instructs the database to remove those Projects that depend on the deleted Student ... if no option is configured, your database will complain with "Constraint violation errors", as the one that you're facing ...这个问题,是从外键Project ,以Student缺少选择:“ON DELETE CASCADE” ......这样的选项指示数据库删除这些Projects依赖于删除的Student ......如果没有选配置,您的数据库会抱怨“约束违反错误”,因为你面临的那个......

It seems that you're creating your database model through hibernate ... to add such option to the constraint to can follow this example ... The result should be something like this:似乎您正在通过休眠创建数据库模型...将此类选项添加到约束中以可以遵循示例...结果应该是这样的:

@Entity
@Table(name = "project")
public class Project {
    ...
    @ManyToOne
    @JoinColumn(
        name = "student_id", 
        nullable = false,
        foreignKey = @ForeignKey(
            name = "FK_STUDENT_ID",
            foreignKeyDefinition = "FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE"
    )
    private Student student;
    ...
}

NOTE : this is just a quick example, you'll have to test it yourself.注意:这只是一个简单的例子,你必须自己测试。

To automatically delete all projects associated with a student on deletion, you could also model the @OneToMany -side like this:要在删除时自动删除与学生关联的所有项目,您还可以像这样对@OneToMany建模:

public class Student {
  ...
  @OneToMany(cascade = CascadeType.REMOVE)
  private Set<Projects> projects; // -> student removal will be cascaded to projects by hibernate
  ...
}

(note that specifying @ManyToOne(cascade = CascadeType.REMOVE) in the Project -entity should be done with care, as the deletion of a project would then try to remove an associated student, even though it could still be associated with projects not to be removed - also see: https://thorben-janssen.com/avoid-cascadetype-delete-many-assocations/ for an example ) (请注意,在Project -entity 中指定@ManyToOne(cascade = CascadeType.REMOVE)应该小心,因为删除项目会尝试删除关联的学生,即使它仍然可以与不删除的项目关联被删除 - 另见: https : //thorben-janssen.com/avoid-cascadetype-delete-many-assocations/示例)


Another option similar to what Carlitos Way suggested could look like that (see https://stackoverflow.com/a/38495206 ):另一个类似于 Carlitos Way 建议的选项可能看起来像这样(参见https://stackoverflow.com/a/38495206 ):

public class Project {
  ...
  @ManyToOne
  @OnDelete(action = OnDeleteAction.CASCADE)
  private Student student; // -> hibernate will generate corresponding DDL
  ...
}

Cascading REMOVE operations from the parent to the child will require a relation from the parent to the child (not just the opposite, which seems to be what you currently have).从父级到子级级联 REMOVE 操作将需要从父级到子级的关系(不仅仅是相反,这似乎是您目前拥有的)。 Having said that, try creating a bi-directional relationship as follows:话虽如此,请尝试创建双向关系,如下所示:

@Entity
@Table(name = "student")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Student implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name")
    private String name;
 
    @OneToMany(mappedBy = "student", cascade = CascadeType.REMOVE)
    private Set<Project> projects;
}

Additionally, consider removing the cascading REMOVE operations from Project otherwise you might end up deleting a Student upon deletion of a Project .此外,请考虑从Project删除级联 REMOVE 操作,否则您可能会在删除Project时删除Student

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM