Ahmed Yusuf
Ahmed Yusuf

Reputation: 499

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

@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?

Upvotes: 1

Views: 1841

Answers (2)

Carlitos Way
Carlitos Way

Reputation: 3424

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 ...

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.

Upvotes: 2

Jo&#227;o Dias
Jo&#227;o Dias

Reputation: 17460

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). 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.

Upvotes: 1

Related Questions