You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@grails.apache.org by "borinquenkid (via GitHub)" <gi...@apache.org> on 2026/10/21 00:24:29 UTC
[I] [Hibernate 7] A unidirectional hasMany that shares a join table with another silently drops addTo* [grails-core]
borinquenkid opened a new issue, #16699:
URL: https://github.com/apache/grails-core/issues/16699
### Expected Behavior
An owner with two unidirectional `hasMany` to the same class that share one join table (no `joinTable` mapping)
```groovy
class Item {
static hasMany = [roles: Role, denyRoles: Role]
}
```
writes a role added to either collection to the join table, or fails the save with an error. `failOnError: true` must not pass while rows are dropped.
### Actual Behaviour
On Hibernate 7 the classic domain binder keeps the rule from #10811 in `CollectionKeyColumnUpdater`: when the owner has more than one unidirectional to-many sharing the collection's join table, the key of each collection is made nullable **and not updatable**. Hibernate 7's collection persister writes no rows for a collection whose key is not updatable, so `addToRoles` and `addToDenyRoles` are both dropped silently and the collections reload empty, even with `failOnError: true`.
#16686 keeps the key updatable for collections with join tables of their own (the reporter's first shape in #16665) and leaves this shared-table case as it was. This issue is the follow-up it points to.
### Analysis
- A local probe by @jdaugherty on #16686 made the key always updatable: both collections of `hasMany = [roles: Role, denyRoles: Role]` were written to the shared table and read back correctly, and the `hasmany` package and the specs of #16686 still passed. So the #10811 rule may not be needed on Hibernate 7 at all, as the reporter suggested in #16665.
- The native domain generator of the 9.x branches already treats the rule as a defect rather than a rule to copy and always makes the key updatable (see the javadoc of `GrailsDomainGenerator.collectionKeyFacets`), so dropping it on 8.x brings the classic binder in line with native binding.
- What needs a look before dropping it: the shared join table has three columns (`item_id`, `item_roles_id`, `item_deny_roles_id`) but the classic binder's unique key covers only the **first** collection's key column with the element column, `UNIQUE (item_roles_id, item_id)`. Rows of the second collection leave `item_roles_id` null. H2 creates the key `NULLS DISTINCT`, but databases that treat nulls as equal in a unique constraint (SQL Server, for example) would reject two `denyRoles` rows for the same role from different owners. Either the unique key has to cover every key column of the table, or each collection needs a unique key of its own, or the binder should give each collection its own join table by default.
### Steps To Reproduce
Register the `Item`/`Role` classes above against the Hibernate 7 datastore of 8.0.x, add a role to each collection, flush, clear the session and reload: both collections are empty. `MultipleUnidirectionalHasManySpec` (from #16686) has the per-collection join table shape; the shared-table shape is `CKCUSharedTableOwner` in `CollectionKeyColumnUpdaterSpec`, which currently asserts the key is not updatable.
### Environment Information
- Grails 8.0.x, `grails-data-hibernate7`, classic domain binding.
Related: #16665, #16686, #10811.
--
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: notifications-unsubscribe@grails.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] [Hibernate 7] A unidirectional hasMany that shares a join table with another silently drops addTo* [grails-core]
Posted by "borinquenkid (via GitHub)" <gi...@apache.org>.
borinquenkid commented on issue #16699:
URL: https://github.com/apache/grails-core/issues/16699#issuecomment-6387644778
Fixed by #16701.
--
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: notifications-unsubscribe@grails.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org