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

   
   ## Steps to reproduce
   
   Two domain classes, a parent with a composite identifier declared as `zeta`, 
`alpha` (not in name order) and a bidirectional one-to-many to a child:
   
   ```groovy
   @Entity
   class Parent implements Serializable {
       String zeta
       String alpha
       static hasMany = [kids: Kid]
   
       static mapping = MappingBuilder.define {
           composite('zeta', 'alpha')
       }
   }
   
   @Entity
   class Kid {
       String name
       static belongsTo = [parent: Parent]
   }
   ```
   
   ```groovy
   Parent.withNewTransaction {
       new Parent(zeta: 'z', alpha: 'a').addToKids(new Kid(name: 
'kid')).save(failOnError: true, flush: true)
   }
   Parent.withNewSession {
       Parent.findByZetaAndAlpha('z', 'a').kids*.name   // [] - expected ['kid']
   }
   ```
   
   The kid is saved with the right foreign key values, and `kid.parent` loads. 
`parent.kids` loads no elements.
   
   Declared as `composite('alpha', 'zeta')`, the same classes load the kids.
   
   ## Expected behaviour
   
   `parent.kids` loads the kids in either declaration order. The declaration 
order of a composite identifier is not meant to change the mapping: Hibernate 
sorts the parts of a composite identifier by name, and the to-one side of the 
association is aligned with that order.
   
   ## Cause
   
   `BidirectionalOneToManyLinker.link` (`grails-data-hibernate7/core`, package 
`org.grails.orm.hibernate.cfg.domainbinding.secondpass`) builds the key of the 
inverse collection by copying the columns of the to-one side (`Kid.parent`). 
Those columns are already in key order (`parent_alpha`, `parent_zeta`). It then 
calls `key.sortProperties()`, which applies the owner identifier's permutation 
a second time: the identifier declared as `zeta`, `alpha` sorts to `alpha`, 
`zeta`, and the permutation moves the already sorted columns to `parent_zeta`, 
`parent_alpha`. The collection is then loaded with the identifier values bound 
to the wrong columns, so the query matches no rows. With `composite('alpha', 
'zeta')` the permutation is the identity, which is why that order works.
   
   The same mismatch shows in the composite chain of 
`CompositeForeignKeyRegistrationOrderSpec`: with the referenced entities 
registered first, `PrbMiddle.leaves` ends up with 
`prb_middle_grand_parent_zeta, prb_middle_grand_parent_alpha, prb_middle_name` 
while `PrbLeaf.middle` is `prb_middle_grand_parent_alpha, 
prb_middle_grand_parent_zeta, prb_middle_name`. `grand.middles` and 
`middle.leaves` load empty in every registration order.
   
   It predates #16539 and does not need a nested composite; it reproduces on 
8.0.x with the two classes above.
   
   ## What has been tried
   
   Marking the copied key sorted instead of re-sorting it (so that 
`sortProperties()` is a no-op on the copy). The collections then load in every 
registration order except the two in which the collection's second pass runs 
before the deferred alignment of the to-one it copies from 
(`CompositeForeignKeySecondPass`, added in #16539): there the copied columns 
are still in declared order, so the copy would have to align the to-one first, 
before copying its columns. That is the same ordering the deferred alignment 
already handles for the keys that reference an identifier, so the fix belongs 
with it.
   
   ## Why it is deferred
   
   #16539 fixes the foreign keys (column names, types, order and the 
registration-order dependence) and the duplicate positional key of the inverse 
collection; this finding is about the columns the inverse collection is loaded 
by, in `BidirectionalOneToManyLinker.link`, and was split out of that PR to 
keep it reviewable. `InverseHasManyCompositeIdentifierOrderSpec` 
(`grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder`)
 pins the repro above as a `@PendingFeature`: the name-order variant passes, 
the out-of-name-order variant is pending and will fail the build as "passes 
unexpectedly" once it is fixed, at which point the annotation is to be removed.
   
   Found by @jdaugherty while reviewing #16539 (review comment 4230978366).
   


-- 
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