Skip to content

Fix: Delete of deeply nested entities compares ids with root instead of parent - #2418

Open
sharanggupta wants to merge 1 commit into
spring-projects:mainfrom
sharanggupta:derived-delete-nested-references
Open

sharanggupta wants to merge 1 commit into
spring-projects:mainfrom
sharanggupta:derived-delete-nested-references

Conversation

@sharanggupta

Copy link
Copy Markdown

Closes #2417

JdbcDeleteQueryCreator.deleteRelations now skips the paths of entities nested in another entity with an id. The recursion for that entity already deletes them, through the right ids.

The new test in JdbcRepositoryWithCollectionsChainHsqlIntegrationTests fails without the change: a child of the other aggregate loses its grandchildren. The spring-data-relational and spring-data-jdbc unit tests and the HSQL integration tests pass.

The delete queries derived by Spring Data JDBC deleted the entities of
every nested path with the ids of the deleted aggregate roots. The back
reference of an entity nested in another entity with an id holds the
id of that other entity, though, so the nested entities of another
aggregate got deleted when their parent had the same id as one of the
deleted roots.

These entities are already deleted by the recursion for the entity
holding the id, which selects those ids from the deleted roots. Skip
them in the loop over the paths of the root.

Signed-off-by: Sharang Gupta <sharang@sharanggupta.dev>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Oct 21, 2026
@sharanggupta

Copy link
Copy Markdown
Author

@schauder, while looking at #2123 I found that the per-entity recursion in JdbcDeleteQueryCreator.deleteRelations is behind three failures, not one: it reuses the root ids for back references that hold other ids (#2417, this PR), it selects the id column names of the parent from the child table (#2123), and for an entity without an id that has nested collections it builds a sub-select without a select list, so a derived delete over nested Lists fails with IllegalStateException: SELECT does not declare a select list.

Rather than patching the recursion three times, I have a branch that builds the nested deletes in one pass over the aggregate's paths, deepest first, where each delete's condition navigates to the root through a sub-select on the table of every ancestor with an id, the way SqlGenerator.getSubselectCondition does for deleteAll:

main...sharanggupta:spring-data-relational:derived-delete-subselects

It carries the regression tests in JdbcRepositoryWithCollectionsChainHsqlIntegrationTests (this PR's, the CHILD_ID rename you suggested on #2128, nested lists without ids, and read-only children, which derived deletes removed although deleteById keeps them), with foreign keys in the schema so that the deepest-first order is exercised. The full relational and JDBC suites pass on HSQL.

If you prefer that direction I can switch this PR to it, which would close #2123 as well; otherwise this PR stays the minimal fix for #2417 and I can offer the id-column fix separately on #2123.

@schauder schauder added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Oct 26, 2026
@schauder schauder changed the title Do not delete other aggregates in derived deletes Delete of deeply nested entities compares ids with root instead of parent Oct 26, 2026
@schauder schauder changed the title Delete of deeply nested entities compares ids with root instead of parent Fix: Delete of deeply nested entities compares ids with root instead of parent Oct 26, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug A general bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Delete of deeply nested entities compares ids with root instead of parent

3 participants