-
Notifications
You must be signed in to change notification settings - Fork 379
Description
Environment
- Spring Boot: 4.0.0
- Spring Data JDBC: 4.0.0
- Database: Postgres 18.1
Description
I was updating from 4.0.0 to 4.0.1 and noticed a behavior change.
I’m concerned this change introduces ambiguous success semantics for save() when the underlying UPDATE affects 0 rows.
I understand the motivation: some databases (e.g., MySQL) can legitimately report 0 affected rows when an entity is saved with values identical to what’s already stored, even though the row exists. That makes throwing IncorrectUpdateSemanticsDataAccessException in that case undesirable.
However, treating 0 updated rows as success also collapses other important cases into the same outcome:
-
Missing row / stale ID: an
UPDATE … WHERE id = ?that matches nothing also returns 0. Previously, the exception made it clear no row was actually updated. Nowsave()appears to succeed even though nothing happened. -
Row-Level Security / policy-based updates: with RLS (or similar update policies), the row may exist but the user is not permitted to update it; postgres will still report
0affected rows. In that case, returning successfully makes it look like the update was applied when it was not.
In other words, 0 rows updated is inherently ambiguous: it can mean no-op update or update didn’t apply. Relying on the update count/exception is currently the only way to detect whether a change was actually applied.
Would it be possible to make this behavior configurable or dialect-specific, or to disambiguate the 0 rows case (e.g., by checking existence when UPDATE returns 0, or providing an opt-in mode that preserves the previous exception behavior)?