JPA Cascadetype.All Does Not Delete Orphans

JPA CascadeType.ALL does not delete orphans

If you are using it with Hibernate, you'll have to explicitly define the annotation CascadeType.DELETE_ORPHAN, which can be used in conjunction with JPA CascadeType.ALL.

If you don't plan to use Hibernate, you'll have to explicitly first delete the child elements and then delete the main record to avoid any orphan records.

execution sequence

  1. fetch main row to be deleted
  2. fetch child elements
  3. delete all child elements
  4. delete main row
  5. close session

With JPA 2.0, you can now use the option orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)

Cascade.Type = ALL does not delete all child rows before trying to delete its own row

You can try to use @OnDelete. As it's stated in the documentation:

... the @OnDelete cascade is a DDL-level FK feature which allows you to remove a child record whenever the parent row is deleted.

So, when annotating the @ManyToOne association with @OnDelete(action = OnDeleteAction.CASCADE), the automatic schema generator will apply the ON DELETE CASCADE SQL directive to the Foreign Key declaration.

Taken this in mind, you can correct your mapping in the following way:

@Entity
@Table(name = "comment_vote")
public class CommentVote {

// ...

@ManyToOne()
@JoinColumn(name="user_id", nullable=false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private User user;

// ...
}

What is the difference between CascadeType.REMOVE and orphanRemoval in JPA?

From here:-

Cascading Remove

Marking a reference field with CascadeType.REMOVE (or CascadeType.ALL,
which includes REMOVE) indicates that remove operations should be
cascaded automatically to entity objects that are referenced by that
field (multiple entity objects can be referenced by a collection
field):

@Entity
class Employee {
:
@OneToOne(cascade=CascadeType.REMOVE)
private Address address;
:
}

Orphan Removal

JPA 2 supports an additional and more aggressive remove cascading mode
which can be specified using the orphanRemoval element of the
@OneToOne and @OneToMany annotations:

@Entity
class Employee {
:
@OneToOne(orphanRemoval=true)
private Address address;
:
}

DIFFERENCE:-

The difference between the two settings is in the response to
disconnecting a relationship. For example, such as when setting the
address field to null or to another Address object.

  • If orphanRemoval=true is specified the disconnected Address instance is automatically removed. This is useful for cleaning up
    dependent objects (e.g. Address) that should not exist without a
    reference from an owner object (e.g. Employee).
  • If only cascade=CascadeType.REMOVE is specified no automatic action is taken since disconnecting a relationship is not a remove

    operation.

JPA CascadeType.REMOVE not working

JPA can only remove and cascade the remove over entities it knows about, and if you have not been maintaining both sides of this bidirectional relationship, issues like this will arise. If the collection of departments is empty, try an em.refresh() before the remove, forcing JPA to populate all relationships so that they can be correctly removed, though it is better to maintain both sides of the relationship as changes are made to avoid the database hit.



Related Topics



Leave a reply



Submit