borinquenkid opened a new issue, #16745:
URL: https://github.com/apache/grails-core/issues/16745

   ## Problem
   
   With Hibernate 7, removing one element from a set of a unidirectional 
`hasMany` deletes every row of that association for the owner, and nothing is 
re-inserted. The remaining elements are lost.
   
   ```groovy
   class Solo {
       String name
       static hasMany = [roles: Role]
   }
   class Role { String name }
   
   // solo has roles one and two, saved and flushed
   solo.removeFromRoles(one)
   solo.save(flush: true)
   // reloaded: solo.roles is empty, expected [two]
   ```
   
   The SQL logged for the flush is a single statement keyed on the owner only, 
with no restriction on the element:
   
   ```
   delete from solo_role where solo_roles_id=?
   ```
   
   ## What I verified
   
   - Reproduced on H2 with a single association on its own join table, so it is 
not specific to a table that associations share. The reproduction is 
`SharedJoinTableBulkDeleteSpec` in `grails-data-hibernate7/core`, feature 
"removing one element of a set on a join table of its own keeps the other 
elements".
   - The same spec fails on `feat/sql-text-8.0.x`, the base of #16701, which 
has none of the shared-table changes, so it is not introduced by #16701.
   - It was also reported on Oracle in the review of #16701. I have not run the 
other databases. The delete is built by Hibernate's persister, not by dialect 
code, so I do not expect it to depend on the database.
   - I have not checked the v8.0.0 release or an earlier Grails line.
   
   ## Likely cause (not confirmed)
   
   Hibernate identifies the row of a set element to delete by the key columns 
plus the element columns that are not nullable. The statement above has no 
element restriction, which is what the persister produces when the element 
column is nullable. I have not traced where the nullability of the join table's 
element column comes from in the Grails binder (the key columns are made 
nullable by `CollectionKeyColumnUpdater`; the element is bound through the 
many-to-one element binder).
   
   ## Why it matters for shared join tables
   
   Two unidirectional `hasMany` associations to the same class that share a 
join table (#16701) have element columns that must be nullable when each 
association has its own element column, so a fix that makes the element column 
`NOT NULL` does not cover that shape. A fix may need a custom delete-row 
statement for collections whose element is nullable, or element identification 
some other way.
   
   ## Tests
   
   Pending features in `SharedJoinTableBulkDeleteSpec`, for a set on its own 
table, for associations with a key column each, and for associations with one 
shared key column.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to