1

I am working on a Spring-MVC application in which I am trying to delete an entity, which has one-to-many relationships with 3 other entities. I have marked the entities to be deleted on Cascade, but it is not working. I am getting an error of foreign key violation..

Notes Entity :

@Entity
@Table(name="groupnotes")
public class GroupNotes {

    @OneToMany(mappedBy = "mnotedata",fetch = FetchType.EAGER,cascade = CascadeType.REMOVE)
    private Set<GroupAttachments> mattachments = new HashSet<>();

    public Set<GroupAttachments> getMattachments() {
        return this.mattachments;
    }

    public void setMattachments(Set<GroupAttachments> mattachments) {

        this.mattachments = mattachments;
    }

    @OneToMany(mappedBy = "mhistory",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    private Set<GroupNoteHistory> groupNoteHistorySet = new HashSet<>();

    public Set<GroupNoteHistory> getGroupNoteHistorySet(){
        return this.groupNoteHistorySet;
    }

    public void setGroupNoteHistorySet(Set<GroupNoteHistory> groupNoteHistorySet){
        this.groupNoteHistorySet = groupNoteHistorySet;
    }

    @OneToMany(mappedBy = "unreadNotes",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    private Set<UnreadNotes> unreadNotesSet = new HashSet<>();

    public Set<UnreadNotes> getUnreadNotesSet(){
        return this.unreadNotesSet;
    }

    public void setUnreadNotesSet(Set<UnreadNotes> unreadNotesSet){
        this.unreadNotesSet = unreadNotesSet;
    }
}

Entity GroupAttachments :

@Entity
@Table(name = "groupattachments")
public class GroupAttachments {
@ManyToOne
    @JoinColumn(name = "mnoteid")
    @OnDelete(action = org.hibernate.annotations.OnDeleteAction.CASCADE)
    private GroupNotes mnotedata;

    public void setMnotedata(GroupNotes mnotedata){this.mnotedata=mnotedata;}

    public GroupNotes getMnotedata(){return mnotedata;}
}

But when I execute the code below :

 @Override
    public boolean deleteAllNotesForSection(int msectionid) {
        session = this.sessionFactory.getCurrentSession();
        org.hibernate.Query query = session.createQuery("from GroupNotes as " +
                "n where n.ownednotes.msectionid=:msectionid");
        query.setParameter("msectionid",msectionid);
        List<GroupNotes> groupNotesList = query.list();
        for(GroupNotes groupNotes : groupNotesList){
            groupNotes.getGroupNoteHistorySet().clear();
            groupNotes.getMattachments().clear();
            groupNotes.getUnreadNotesSet().clear();
            session.flush();
        }

        org.hibernate.Query query1 = session.createQuery("delete from GroupNotes as " +
                "n where n.ownednotes.msectionid=:msectionid");
        query1.setParameter("msectionid",msectionid);
        query1.executeUpdate();
        session.flush();
        return true;
    }

I get the following error when I execute the above code :

SEVERE: Servlet.service() for servlet [appServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause
org.postgresql.util.PSQLException: ERROR: update or delete on table "groupnotes" violates foreign key constraint "groupnotes_groupnotehistory_fk" on table "groupnotehistory"
  Detail: Key (mnoteid)=(5455) is still referenced from table "groupnotehistory".

Isn't the first query which clears all the set, should clear from the database the history and all. And ideally there shouldn't be a problem, as it is cascade delete. I also tried retrieving the List using query1.list and deleting in a for-loop, that also didn't work. I don't understand how to remedy this. Thanks a lot.

We are Borg
  • 5,117
  • 17
  • 102
  • 225

1 Answers1

2

Several things are wrong here. First, calling clear() handles just one side of bidirectional relation. You need to visit every child and set its reference to GroupNote to null. The way you wrote it, the database will stay the same after flush, no entities will be deleted.

Second, calling delete in HQL bypasses cascade options. So even without the first problem, no related entities will be deleted this way, leading to the exception you are seeing.

Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
  • But when I am just calling a note delete function, for a note which has NoteHistory and Attachment, then it works fine, only when I want to delete a bunch of notes together, then I am getting an error. That is why I cannot understand, as there is a DAO method where I am doing getById from database and using session.delete(note_object_name) and session.flush(), then it works. – We are Borg May 11 '15 at 12:50