tm1701
tm1701

Reputation: 7581

Hibernate: cannot cascading delete unidirectional parent of children

When deleting the parent of children (in a 1 to many unidirectional relation) I keep on getting these errors. When I delete the children first, everything works OK.

I don't need/want a bi-directional relationship.

This is the parent:

@Entity
@Table(name = "datagroup")
public class DataGroup implements java.io.Serializable {
    @Id
    @Column(name = "group_id", unique = true, nullable = false)
    private int         group_id;
    private String      name;

    @OneToMany( targetEntity=DataGroupItem.class, fetch=FetchType.LAZY, cascade = CascadeType.REMOVE)
    @JoinColumn(name="group_id")
    private List<DataGroupItem> dataGroupItems = new ArrayList<>( 0);
    ... setters and getters
}

And this is the child:

@Entity
@Table(name = "datagroupitems")
public class DataGroupItem implements java.io.Serializable {
    @Id
    @Column(name = "item_id", nullable = false)
    private int item_id;
    private String name;

    @Column(name = "group_id", nullable = false)
    private int group_id = 0; // only for (un)delete
    ... getters and setters
}

When deleting the parent in a Controller I do:

@RestController
@RequestMapping("/learner/groups")
public class LearnerSyncServices {
    @Autowired
    private IDataGroupRepository dataGroupRepository;
    @Autowired
    private IDataGroupItemRepository dataGroupItemRepository;
    ... 

    @RequestMapping( method= RequestMethod.DELETE, value="/{id}")
    public void delete(@PathVariable String id) {
        try {
            int idx = Integer.parseInt( id);
            dataGroupRepository.delete( idx);
        } catch (Exception e) {
            logger.error( "Cannot delete " + id + "  " + e.getMessage());
        }
    }

As JPA version I have: Spring boot version 4.1.3.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

Deleting the group with at least 1 child gives the following messages:

.. WARN  org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 1048, SQLState: 23000
.. ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Column 'group_id' cannot be null
.. INFO  org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl - HHH000010: On release of batch it still contained JDBC statements
.. ERROR nl.deholtmans.tjm1706.learner.LearnerSyncServices - Cannot delete 101  could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

Upvotes: 1

Views: 2042

Answers (1)

crizzis
crizzis

Reputation: 10716

When deleting the DataGroup, hibernate first tries to issue the SQL statement that will delete the parent, and then proceeds to issue statements that remove the children.

When deleting the parent, the foreign key in the datagroupitems table must be set to NULL to maintain db consistency (at that point, it is not obvious to the db that children rows are going to be deleted as well). However, it cannot be set to NULL because you specifically forbade it in your schema definition.

Hibernate simply does not know it should delete children first, parent last. You can fix this by allowing the group_id column to be nullable.

EDIT If you're not using 'hbm2ddl.auto/javax.persistence.schema-generation.database.action', do not forget to recreate/manually update your db schema. The NOT NULL constraint needs to be dropped from the database for this solution to work.

Upvotes: 1

Related Questions