javahibernatehibernate-cascade

How to properly delete a complex object using Hibernate?


Here is the problem. When I'm trying to delete a Catalog object from database, Hibernate also removing all Catalog objects with associated Type and Genre Ids. For example, if I’m removing Catalog with Type.id=1 and Genre.id=1 Hibernate delete every Catalogs with such Ids. Any ideas how to fix it? I need to delete only one Catalog object without deleting Type and Genre objects with id=1.

@Entity
@Table(name = "catalog", catalog = "media_store_db")
public class Catalog implements Serializable {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "product_name", length = 100)
    private String productName;

    @ManyToOne(cascade = {CascadeType.ALL})
    @JoinColumn(name = "genre_id", referencedColumnName = "genre_id")
    private Genre genre;

    @ManyToOne(cascade = {CascadeType.ALL})
    @JoinColumn(name = "type_id", referencedColumnName = "type_id")
    private Type type;


@Entity
@Table(name = "genres", catalog = "media_store_db")
public class Genre implements Serializable {

    @Id
    @Column(name = "genre_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "genre_name")
    private String name;

    @OneToMany(mappedBy = "genre", cascade = CascadeType.ALL)
    Collection<Catalog> catalogs = new ArrayList<Catalog>();

@Entity
@Table(name = "types", catalog = "media_store_db")
public class Type implements Serializable {

    @Id
    @Column(name = "type_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "type_name")
    private String name;

    @OneToMany(mappedBy = "type", cascade = CascadeType.ALL)
    Collection<Catalog> catalogs = new ArrayList<Catalog>();

My method which delete a Catalog object

public void deleteCatalog(Integer catalogId) {
        Session session = config.getSession();
        Transaction tx = session.beginTransaction();
        session.delete(session.get(Catalog.class, catalogId));
        tx.commit();
        session.close();
}

Solution

  • This is because of Cascade.ALL. If you delete a parent if would also delete all related child if you are using Cascade.ALL.

    Instead ALL choose only what you need from the below

    CascadeType.PERSIST: cascades the persist (create) operation to associated entities if persist() is called or if the entity is managed

    CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed

    CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called

    CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called

    CascadeType.DETACH: cascades the detach operation to associated entities if detach() is called

    CascadeType.ALL: all of the above