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/10 19:57:03 UTC

[PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

borinquenkid opened a new pull request, #16574:
URL: https://github.com/apache/grails-core/pull/16574

   ## Problem
   
   An inverse `hasMany` on an entity with a composite identifier that is not declared in name order loads no elements. With `composite('zeta', 'alpha')` and `static hasMany = [kids: Kid]` (`Kid belongsTo = [parent: Parent]`), `parent.kids` is empty while `kid.parent` loads. With `composite('alpha', 'zeta')` it works. In the three level `PrbGrand`/`PrbMiddle`/`PrbLeaf` chain, `grand.middles` and `middle.leaves` loaded empty in every registration order.
   
   `BidirectionalOneToManyLinker.link` copies the columns of the to-one side, which the composite foreign key alignment of #16539 has put in identifier order already, and then called `key.sortProperties()`, which applied the owner identifier's permutation a second time. The collection key therefore ended up in a different column order than the to-one key (`prb_middle_grand_parent_zeta, prb_middle_grand_parent_alpha, prb_middle_name` against `..._alpha, ..._zeta, ..._name`), so the identifier values were bound to the wrong columns. The analysis is jdaugherty's, from the review of #16539.
   
   ## Impact
   
   Hibernate 7 on 8.0.x: any inverse `hasMany`/`oneToMany` whose owner has a composite identifier declared out of name order silently loads an empty collection. Saving and the to-one side are unaffected. Single column identifiers and identifiers declared in name order are unaffected, and the DDL does not change.
   
   ## Fix
   
   The linker marks the copied key as sorted instead of re-sorting it, so the collection key ends with exactly the column order and types of the to-one side. The collection's second pass can run before the deferred `CompositeForeignKeySecondPass` of the to-one side (two of the registration orders of the chain), so the linker first calls the idempotent `alignWithReferencedIdentifier` on the to-one side, which does nothing when it is aligned already. The result is independent of the registration order. `BidirectionalOneToManyLinker` takes the `CompositeIdentifierToManyToOneBinder` for this.
   
   ## Tests
   
   Red before the fix, green after (all 14 new iterations failed with the collection empty: the simple parent/kid case in both registration orders, the chain in all 6 and the hub children in all 6):
   
   - `InverseHasManyCompositeIdentifierOrderSpec`: the previously `@PendingFeature` case is now a plain feature over the 2 registration permutations of `IhmParent`/`IhmKid`; it saves, reloads in a new session and asserts the kids, and that the collection key columns equal the to-one foreign key columns in order. The name-order case still passes (3 tests).
   - `CompositeForeignKeyRegistrationOrderSpec`: two new features. The three level chain over the 6 permutations of `PrbGrand`/`PrbMiddle`/`PrbLeaf` asserts `grand.middles` and `middle.leaves` load after save and a session clear and are keyed like their to-one side. The hub layout (`PrbHub`, multi-column nested part between plain parts, `PrbHubChild`) over the 6 permutations asserts the children load and are keyed like the hub key. The spec now runs 49 iterations.
   - `BidirectionalOneToManyLinkerSpec`: two new unit features (the copy is marked sorted and Hibernate does not permute it again; the to-one side is aligned once, before the key copies its columns). `CollectionKeyBinderSpec` and `CollectionSecondPassBinderSpec` use the new constructor.
   - `:grails-data-hibernate7-core:test` passes in full (3714 tests, 0 failures, 15 skipped), `checkstyleMain` and `codenarcMain` are clean. `CompositeForeignKeyColumnTypesSpec` and the existing foreign key and DDL specs are unchanged and pass.
   
   Fixes #16565
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "borinquenkid (via GitHub)" <gi...@apache.org>.
borinquenkid commented on code in PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#discussion_r4330542052


##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy:
##########
@@ -18,6 +18,7 @@
  */
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 
+import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder

Review Comment:
   Removed in cad1bf8a7f.



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy:
##########
@@ -20,6 +20,7 @@
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 
 
+import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder

Review Comment:
   Removed in cad1bf8a7f.



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinkerSpec.groovy:
##########
@@ -80,4 +87,72 @@ class BidirectionalOneToManyLinkerSpec extends HibernateGormDatastoreSpec {
         !key.isForeignKeyEnabled()
         !key.isConstrained()
     }
+
+    void "the copied key is marked sorted so Hibernate does not apply the identifier permutation to it again"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        BasicValue value = new BasicValue(metadataContext, table)
+        value.addColumn(new Column("owner_id"))
+        otherSideProperty.setValue(value)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateToManyProperty otherSide = Mock(HibernateToManyProperty)
+        otherSide.getName() >> "owner"
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then:
+        key.isSorted()

Review Comment:
   Agreed: this feature only checks that the flag is set on the copied key, and that was already true under `sortProperties()`. The feature below is the one that tells the two apart now (see the reply there).



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinkerSpec.groovy:
##########
@@ -80,4 +87,72 @@ class BidirectionalOneToManyLinkerSpec extends HibernateGormDatastoreSpec {
         !key.isForeignKeyEnabled()
         !key.isConstrained()
     }
+
+    void "the copied key is marked sorted so Hibernate does not apply the identifier permutation to it again"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        BasicValue value = new BasicValue(metadataContext, table)
+        value.addColumn(new Column("owner_id"))
+        otherSideProperty.setValue(value)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateToManyProperty otherSide = Mock(HibernateToManyProperty)
+        otherSide.getName() >> "owner"
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then:
+        key.isSorted()
+        0 * binder._
+    }
+
+    void "the to-one side is aligned with the identifier of the owner before its columns are copied"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        ManyToOne toOneValue = new ManyToOne(metadataContext, table)
+        toOneValue.addColumn(new Column("owner_alpha"))
+        toOneValue.addColumn(new Column("owner_zeta"))
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        otherSideProperty.setValue(toOneValue)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateCompositeIdentity compositeId = Mock(HibernateCompositeIdentity)
+        GrailsHibernatePersistentEntity ownerEntity = Mock(GrailsHibernatePersistentEntity) {
+            getHibernateCompositeIdentity() >> Optional.of(compositeId)
+        }
+        HibernateManyToOneProperty otherSide = Mock(HibernateManyToOneProperty) {
+            getName() >> "owner"
+            getHibernateAssociatedEntity() >> ownerEntity
+        }
+        List<String> columnsWhenAligned = null
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then: 'the to-one side is aligned once, before the key exists'
+        1 * binder.alignWithReferencedIdentifier(otherSide, toOneValue, compositeId, ownerEntity) >> {
+            columnsWhenAligned = key.columns*.name
+        }
+        columnsWhenAligned == []
+
+        and: 'the key copies the aligned columns and Hibernate leaves their order alone'
+        key.columns*.name == ['owner_alpha', 'owner_zeta']
+        key.isSorted()
+        key.sortProperties() == null

Review Comment:
   Done in cad1bf8a7f: the key now wraps an embedded `Component` prototype whose properties are declared out of name order (`zeta`, `alpha`), so `sortProperties()` returns a real permutation for a key the linker did not mark sorted and `null` for one it did. The assertion fails without `setSorted(true)` and passes with it, which is what the `and:` label claims.



##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinker.java:
##########
@@ -67,6 +81,20 @@ public void link(
             key.addColumn(mappingColumn);
             key.getTable().addColumn(mappingColumn);
         }
-        key.sortProperties();
+        key.setSorted(true);

Review Comment:
   Added to the class javadoc in cad1bf8a7f: marking the key sorted is required, not only a way to skip the permutation, because `MappingModelCreationHelper.getPropertyOrder` asserts it and otherwise maps the columns through the identifier component's original property order again.



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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6343720956

   ## 🔎 No tests executed 🔎
   
   🏷️ Commit: 7ba719320b1d6441990614f729e0ac29b942b29a
   ▶️ Tests:  0 executed
   ⚪️ Checks: 46/46 completed
   
   ---
   _Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
   


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6305288120

   ## 🚨 TestLens detected 1 failed test 🚨
   
   ### Test Summary
   > [!TIP]
   > Inspect all details with the [TestLens CLI](https://testlens.app/docs/features/cli): `testlens pr 16574`
   
   #### [Groovy Snapshot Canary Build / Build Grails \(shard 2\)](https://github.com/apache/grails-core/actions/runs/39501016661/job/118949473304?pr=16574) > :grails-data-mongodb-spring-boot:test
   
   | Test | Runs | Flakiness |
   |---|---|--:|
   | MongoDbGormAutoConfigurationSpec | ❌ | 0%&nbsp;🟢 |
   
   🏷️ Commit: cad1bf8a7f34da9bc75a659e8928a5d49593c8a1
   ▶️ Tests:  77352 executed
   🟡 Checks: 87/90 completed
   
   ### Test Failures
   
   <details><summary><strong>MongoDbGormAutoConfigurationSpec</strong> (:grails-data-mongodb-spring-boot:test in <a href="https://github.com/apache/grails-core/actions/runs/39501016661/job/118949473304?pr=16574">Groovy Snapshot Canary Build / Build Grails (shard 2)</a>)</summary>
   
   ```
   org.testcontainers.containers.ContainerLaunchException: Container startup failed for image mongo:8.0
   	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:346)
   	at org.testcontainers.containers.GenericContainer.start(GenericContainer.java:317)
   	at org.apache.grails.testing.mongo.MongoContainerHolder.startMongoContainer(MongoContainerHolder.groovy:42)
   	at org.apache.grails.testing.mongo.MongoContainerHolder.getContainer(MongoContainerHolder.groovy:53)
   	at org.apache.grails.testing.mongo.StartMongoGrailsUnitExtension.visitSpec_closure1(StartMongoGrailsUnitExtension.groovy:78)
   	at org.spockframework.runtime.extension.MethodInvocation.proceed(MethodInvocation.java:139)
   	at org.spockframework.runtime.model.MethodInfo.invoke(MethodInfo.java:157)
   	at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
   Caused by: org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
   	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
   	at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:331)
   	... 7 more
   Caused by: org.testcontainers.containers.ContainerLaunchException: Could not create/start container
   	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:551)
   	at org.testcontainers.containers.GenericContainer.lambda$doStart$0(GenericContainer.java:341)
   	at org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:81)
   	... 8 more
   Caused by: java.lang.IllegalStateException: Wait strategy failed. Container exited with code 1
   	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:520)
   	... 10 more
   Caused by: org.testcontainers.containers.ContainerLaunchException: Timed out waiting for log output matching '(?i).*waiting for connections.*'
   	at org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy.waitUntilReady(LogMessageWaitStrategy.java:47)
   	at org.testcontainers.containers.wait.strategy.AbstractWaitStrategy.waitUntilReady(AbstractWaitStrategy.java:52)
   	at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:904)
   	at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:487)
   	... 10 more
   ```
   
   </details>
   
   ### Rerun Controls
   > [!NOTE]
   > Checks are currently running using the configuration below.
   
   Select tests to mute in this pull request:
   
   🔲 MongoDbGormAutoConfigurationSpec <!-- uniqueId=[engine:spock]/[spec:org.grails.datastore.gorm.mongodb.boot.autoconfigure.MongoDbGormAutoConfigurationSpec] -->
   
   Reuse successful test results:
   
   🔲 ♻️ Only rerun the tests that failed or were muted before
   
   Click the checkbox to trigger a rerun:
   
   🔲 **Rerun jobs**
   
   ---
   _Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
   


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "jdaugherty (via GitHub)" <gi...@apache.org>.
jdaugherty commented on code in PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#discussion_r4289862618


##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionKeyBinderSpec.groovy:
##########
@@ -18,6 +18,7 @@
  */
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 
+import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder

Review Comment:
   Duplicate import: the same class is imported again on line 24. CodeNarc's `DuplicateImport` rule is enabled but the style tasks skip test sources, so this is a cleanup rather than a gate failure.



##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinker.java:
##########
@@ -67,6 +81,20 @@ public void link(
             key.addColumn(mappingColumn);
             key.getTable().addColumn(mappingColumn);
         }
-        key.sortProperties();
+        key.setSorted(true);

Review Comment:
   Non-blocking. A sentence in the class javadoc that this flag is required, not only a way to skip the sort, would protect it from a later simplification: `MappingModelCreationHelper.getPropertyOrder` asserts the collection key is sorted and, when it is not, maps the key's columns through the identifier component's original property order. With this line removed, `InverseHasManyCompositeIdentifierOrderSpec` fails in `initializationError` with that `AssertionError` while the session factory is built.



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinkerSpec.groovy:
##########
@@ -80,4 +87,72 @@ class BidirectionalOneToManyLinkerSpec extends HibernateGormDatastoreSpec {
         !key.isForeignKeyEnabled()
         !key.isConstrained()
     }
+
+    void "the copied key is marked sorted so Hibernate does not apply the identifier permutation to it again"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        BasicValue value = new BasicValue(metadataContext, table)
+        value.addColumn(new Column("owner_id"))
+        otherSideProperty.setValue(value)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateToManyProperty otherSide = Mock(HibernateToManyProperty)
+        otherSide.getName() >> "owner"
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then:
+        key.isSorted()
+        0 * binder._
+    }
+
+    void "the to-one side is aligned with the identifier of the owner before its columns are copied"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        ManyToOne toOneValue = new ManyToOne(metadataContext, table)
+        toOneValue.addColumn(new Column("owner_alpha"))
+        toOneValue.addColumn(new Column("owner_zeta"))
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        otherSideProperty.setValue(toOneValue)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateCompositeIdentity compositeId = Mock(HibernateCompositeIdentity)
+        GrailsHibernatePersistentEntity ownerEntity = Mock(GrailsHibernatePersistentEntity) {
+            getHibernateCompositeIdentity() >> Optional.of(compositeId)
+        }
+        HibernateManyToOneProperty otherSide = Mock(HibernateManyToOneProperty) {
+            getName() >> "owner"
+            getHibernateAssociatedEntity() >> ownerEntity
+        }
+        List<String> columnsWhenAligned = null
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then: 'the to-one side is aligned once, before the key exists'
+        1 * binder.alignWithReferencedIdentifier(otherSide, toOneValue, compositeId, ownerEntity) >> {
+            columnsWhenAligned = key.columns*.name
+        }
+        columnsWhenAligned == []
+
+        and: 'the key copies the aligned columns and Hibernate leaves their order alone'
+        key.columns*.name == ['owner_alpha', 'owner_zeta']
+        key.isSorted()
+        key.sortProperties() == null

Review Comment:
   Non-blocking. For a key that wraps `null`, this assertion and the column check after it hold with or without `setSorted(true)`: `DependantValue.sortProperties()` only permutes columns when the wrapped value is a `SortableValue`, so here it returns null and leaves the columns alone either way. To make the `and:` label true, give the key an embedded `Component` prototype whose properties are declared out of name order (say `zeta`, `alpha`, with `setEmbedded(true)`): `sortProperties()` then returns a real permutation, and the assertion fails on a key the linker did not mark sorted and passes on one it did. The integration specs cover the behavior end to end, so this is only about what the unit test proves.



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/CollectionSecondPassBinderSpec.groovy:
##########
@@ -20,6 +20,7 @@
 package org.grails.orm.hibernate.cfg.domainbinding.secondpass
 
 
+import org.grails.orm.hibernate.cfg.domainbinding.binder.CompositeIdentifierToManyToOneBinder

Review Comment:
   Same here: duplicate of the import on line 39.



##########
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/cfg/domainbinding/secondpass/BidirectionalOneToManyLinkerSpec.groovy:
##########
@@ -80,4 +87,72 @@ class BidirectionalOneToManyLinkerSpec extends HibernateGormDatastoreSpec {
         !key.isForeignKeyEnabled()
         !key.isConstrained()
     }
+
+    void "the copied key is marked sorted so Hibernate does not apply the identifier permutation to it again"() {
+        given:
+        def metadataContext = getGrailsDomainBinder().getMetadataBuildingContext()
+        RootClass rootClass = new RootClass(metadataContext)
+        rootClass.setEntityName("TestEntity")
+        Table table = new Table("test_table")
+        rootClass.setTable(table)
+        Property otherSideProperty = new Property()
+        otherSideProperty.setName("owner")
+        BasicValue value = new BasicValue(metadataContext, table)
+        value.addColumn(new Column("owner_id"))
+        otherSideProperty.setValue(value)
+        rootClass.addProperty(otherSideProperty)
+        Collection collection = new Bag(metadataContext, rootClass)
+        DependantValue key = new DependantValue(metadataContext, new Table("collection_table"), null)
+        HibernateToManyProperty otherSide = Mock(HibernateToManyProperty)
+        otherSide.getName() >> "owner"
+
+        when:
+        linker.link(collection, rootClass, key, otherSide)
+
+        then:
+        key.isSorted()

Review Comment:
   Non-blocking. `key.isSorted()` was true under the old `sortProperties()` call too, since that call sets the flag, so this feature passes on 8.0.x unchanged. The note on the `sortProperties() == null` assertion below has a shape that tells the two apart.



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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6314407807

   ## 🚨 All tests passed but jobs failed 🚨
   
   ### Failed Jobs without Test Failures
   
   ❌ [Code Style / Forge Projects](https://github.com/apache/grails-core/actions/runs/39588719975/job/119184014134?pr=16574)
   
   🏷️ Commit: 661fd410bf2bc033621fcf5ddc5fc10c35d2ded2
   ▶️ Tests:  270 executed
   🟡 Checks: 5/81 completed
   
   ### Rerun Controls
   
   Click the checkbox to trigger a rerun:
   
   🔲 **Rerun jobs**
   
   ---
   _Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
   


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "borinquenkid (via GitHub)" <gi...@apache.org>.
borinquenkid merged PR #16574:
URL: https://github.com/apache/grails-core/pull/16574


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6102540609

   ## ✅ All tests passed ✅
   
   🏷️ Commit: 082646f112be03ebd920ba32d0e5638256387a4a
   ▶️ Tests:  92656 executed
   ⚪️ Checks: 87/87 completed
   
   ---
   _Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
   


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "codecov[bot] (via GitHub)" <gi...@apache.org>.
codecov[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6102053805

   ## [Codecov](https://app.codecov.io/gh/apache/grails-core/pull/16574?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
   :white_check_mark: All modified and coverable lines are covered by tests.
   :white_check_mark: Project coverage is 59.5844%. Comparing base ([`bfa7093`](https://app.codecov.io/gh/apache/grails-core/commit/bfa709384d5e03de3a4bd77c3e12e9b80d37e4e2?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`082646f`](https://app.codecov.io/gh/apache/grails-core/commit/082646f112be03ebd920ba32d0e5638256387a4a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
   
   <details><summary>Additional details and impacted files</summary>
   
   
   
   [![Impacted file tree graph](https://app.codecov.io/gh/apache/grails-core/pull/16574/graphs/tree.svg?width=650&height=150&src=pr&token=qJrryhpk7u&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)](https://app.codecov.io/gh/apache/grails-core/pull/16574?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   
   ```diff
   @@                Coverage Diff                 @@
   ##                8.0.x     #16574        +/-   ##
   ==================================================
   - Coverage     59.5890%   59.5844%   -0.0046%     
   - Complexity      25035      25037         +2     
   ==================================================
     Files            2175       2175                
     Lines          108651     108651                
     Branches        19821      19821                
   ==================================================
   - Hits            64744      64739         -5     
   - Misses          34965      34970         +5     
     Partials         8942       8942                
   ```
   [see 5 files with indirect coverage changes](https://app.codecov.io/gh/apache/grails-core/pull/16574/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)
   </details>
   <details><summary> :rocket: New features to boost your workflow: </summary>
   
   - :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
   - :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
   </details>


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


Re: [PR] Hibernate 7: load an inverse hasMany whose composite identifier is not declared in name order [grails-core]

Posted by "testlens-app[bot] (via GitHub)" <gi...@apache.org>.
testlens-app[bot] commented on PR #16574:
URL: https://github.com/apache/grails-core/pull/16574#issuecomment-6184316595

   ## 🚨 All tests passed but jobs failed 🚨
   
   ### Failed Jobs without Test Failures
   
   ❌ [CI / Build Grails-Core \(Windows JDK 25 shard 0\)](https://github.com/apache/grails-core/actions/runs/38677526623/job/116234419559?pr=16574)
   
   🏷️ Commit: ce74378714f782e03d79922e147bf89ad27e312c
   ▶️ Tests:  76150 executed
   🟡 Checks: 50/84 completed
   
   ### Rerun Controls
   
   Click the checkbox to trigger a rerun:
   
   🔲 **Rerun jobs**
   
   ---
   _Learn more about TestLens at [testlens.app/docs](https://testlens.app/docs/features/pr-comment/)._
   


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