DEV Community

Cover image for @OnDelete(CASCADE) vs CascadeType.REMOVE in Spring Boot: What’s the Difference?
Yaroslav Ivanovskyi
Yaroslav Ivanovskyi

Posted on

@OnDelete(CASCADE) vs CascadeType.REMOVE in Spring Boot: What’s the Difference?

I ran into a subtle issue the other day while working on a Spring Boot project, and it reminded me how easy it is to confuse @OnDelete(action = OnDeleteAction.CASCADE) with CascadeType.REMOVE. If you're using JPA and Hibernate and trying to cascade deletes between entities, you've probably seen both. They seem to do the same thing - but they don’t.

CascadeType.REMOVE: JPA-Level Cascade

Let’s start with the more familiar one: CascadeType.REMOVE. This is part of standard JPA. When you annotate a relationship like this:

@OneToMany(mappedBy = "post", cascade = CascadeType.REMOVE)
private List<Comment> comments;
Enter fullscreen mode Exit fullscreen mode

it means: “When I delete the parent entity (in this case, Post), go ahead and also delete the child entities (Comments).

But here’s the catch: JPA does this in Java, not in the database. That means it will:

  • Load all the child entities into memory
  • Delete them one by one using separate SQL DELETE statements

If you have only a few children, that’s fine. But if your Post has 1,000+ Comments? Now we’re talking potential performance issues. I've seen apps hit OutOfMemoryErrors from this when dealing with massive datasets.

@OnDelete(action = OnDeleteAction.CASCADE): Let the DB Handle It

This one’s a Hibernate-specific feature. You use it on the child side of the relationship:

@ManyToOne
@JoinColumn(name = "post_id")
@OnDelete(action = OnDeleteAction.CASCADE)
private Post post;
Enter fullscreen mode Exit fullscreen mode

It tells Hibernate: “Don’t bother deleting this entity in Java — let the database take care of it using a foreign key with ON DELETE CASCADE.

So when you delete a Post, the database itself will automatically remove the related Comments - no fetching, no iteration, no extra DELETEs. It’s much faster and more efficient.

Note: @OnDelete is a Hibernate-specific annotation and not part of standard JPA. If you switch to another JPA provider, it may not work.

So Which One Should You Use?

Use CascadeType.REMOVE if:

  • You’re dealing with a small number of child entities — the overhead of loading and deleting them in memory isn’t a big deal.

  • You want your code to be JPA-compliant and database-independent — maybe you’re targeting multiple databases or just don’t want to rely on DB-specific features.

  • You don’t control the schema, or you’re not sure if the database supports ON DELETE CASCADE — or you just want to avoid modifying foreign key constraints.

Use @OnDelete(CASCADE) if:

  • You expect lots of related data — hundreds or thousands of rows, for example.
  • You care about performance and want to avoid loading child entities into memory just to delete them.
  • You’re using Hibernate and you’re comfortable tweaking the database schema — this approach depends on having the right ON DELETE CASCADE setup in your DB.

This article focuses on common use cases in JPA and Hibernate based on real-world experience. There are deeper edge cases I’ve left out for clarity. Feedback welcome!

Top comments (0)