Hibernate cascade delete orphan

8.6k views Asked by At

I have 2 entities: News and NewsComment

@Entity
@Table(name = "news", schema = "city")
public class News {

        private Set<CommentNews> comments = new HashSet<CommentNews>();
        ...
    @OneToMany(cascade={javax.persistence.CascadeType.ALL})
    @Cascade(CascadeType.DELETE_ORPHAN)
    @JoinColumn(name="news_id")
    public Set<CommentNews> getComments() {
        return comments;
    }
}

and

@Entity
@Table(name = "comment_news", schema = "city")
public class CommentNews {
private News news;            
    ...

    @ManyToOne
@Cascade(CascadeType.DELETE_ORPHAN)
@JoinColumn(name = "news_id")
public News getNews() {
    return news;
}
}

and code like this one:

public void delete(int id) {
        T obj = null;
        session = HibernateUtil.openSession();
        try {
            session.beginTransaction();
            obj = (T) session.get(persistentClass, id);
            session.delete(obj);
            session.getTransaction().commit();
        } catch (HibernateException e) {
            session.getTransaction().rollback();
        } finally {
            session.close();
        }
    }

I get

Hibernate: update city.comment_news set news_id=null where news_id=?
    WARN : org.hibernate.util.JDBCExceptionReporter - SQL Error: 1048, SQLState: 23000
    ERROR: org.hibernate.util.JDBCExceptionReporter - Column 'news_id' cannot be null
    ERROR: org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
    org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
Column 'news_id' cannot be null

I want cascade delete News and CommentNews together

1

There are 1 answers

1
Alex Barnes On BEST ANSWER

The mapping here is incorrect:

On the owned side you should use mappedBy to show that the mapping (JoinColumn) is on the other side. You shouldn't have JoinColumn on both sides.

You should use the JPA annotations which include the orphanRemoval property as part of the OneToMany.

@Entity
@Table(name = "news", schema = "city")
public class News {
    @OneToMany(mappedBy = "news", cascade={javax.persistence.CascadeType.ALL}, orphanRemoval = true)
    public Set<CommentNews> getComments() {
        return comments;
    }
}

and on the owning side you shouldn't declare the cascade behaviour. This was done on the owned side.

@Entity
@Table(name = "comment_news", schema = "city")
public class CommentNews {
    @ManyToOne
    @JoinColumn(name = "news_id")
    public News getNews() {
        return news;
    }
}

Hope that works for you.