Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Data JPA derived delete versus bulk delete: callbacks and memory cost

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A derived delete loads matching entities for removal; a JPQL delete issues a bulk statement and skips entity removal callbacks.

The names hide different work

Deleting expired ParcelHold rows by a derived delete method first selects the matching entities and removes them one by one. That path can run @PreRemove and JPA cascades. A JPQL delete sends one statement to the database; already managed ParcelHold objects stay stale and entity callbacks are bypassed. The SQL count can match while the application behavior differs.

Put side effects outside lifecycle assumptions

If removal must publish a durable event, write an outbox row in the same transaction through an explicit service, then delete under a policy whose behavior you test. An entity callback alone is a poor substitute for transaction-aware effects or an outbox. Bulk delete is a reasonable fit for maintenance data when the business contract does not depend on callbacks or entity-level cascades.

Bound the operation

A derived delete of 64 rows may be ordinary; one that loads millions of rows can exhaust heap before flush. Partition by a stable key and measure query count, memory and lock duration. A bulk delete still needs an indexed predicate and an explicit transaction. This example is an interface sketch, not a measured throughput result.

Implementation sketch

Java
long deleteByTenantIdAndExpiredTrue(String tenantId);

@Modifying(clearAutomatically = true)
@Query("delete from ParcelHold h where h.tenantId = :tenantId " +
       "and h.expired = true")
int deleteExpiredInBulk(String tenantId);

Cost and verification

Derived deletion uses O(n) entity memory for n matches and may issue multiple deletes; bulk JPQL can use one statement but bypasses per-entity work. Database scan and lock costs still depend on the predicate and indexes.

Common Mistakes

  • Do not expect @PreRemove to fire for a JPQL bulk delete.
  • Do not infer low memory use from a derived method returning only a count.
  • Do not switch deletion style without checking cascades, audit and outbox contracts.

Read next

Spring Data JPA bulk update: the managed entity can still hold the old value, Spring JPA entity lifecycle: managed changes and detached objects, Spring outbox transaction boundaries: where atomicity ends, Spring JPA fetch plans: measure N+1 queries before changing mappings.

spring
spring-boot
data-transactions
jpa-derived-delete-lifecycle
Storage details