Skip to content

feat: GORM O(M+N) scaling — Hibernate 7 adapter wiring and child data…#15774

Closed
borinquenkid wants to merge 1 commit into
feat/gorm-registry-adaptersfrom
feat/gorm-registry-h7
Closed

feat: GORM O(M+N) scaling — Hibernate 7 adapter wiring and child data…#15774
borinquenkid wants to merge 1 commit into
feat/gorm-registry-adaptersfrom
feat/gorm-registry-h7

Conversation

@borinquenkid

Copy link
Copy Markdown
Member

…store init

Wires Hibernate 7 to the new GormRegistry with correct child datastore initialization order, fixing the gaps that PR #15771 intentionally deferred:

  • HibernateDatastore (H7): registers child datastores with GormRegistry eagerly during initialization, preserving schema/database/datasource routing
  • HibernateGormInstanceApi: use getHibernateTemplate() lazy getter for isAttached(), lock(), and attach() — factory constructor leaves the field null
  • HibernateGormStaticApi: executeQuery(query, Map) passes params as both named params and query settings so max/offset pagination is applied
  • HibernateSession: coerceId() converts String IDs to the entity's declared identifier type in retrieveAll(), fixing String→Long lookup mismatch
  • HibernateGormEnhancerSpec: updated to use GormRegistry public API
  • HibernateDirtyCheckingSpec / HibernateUpdateFromListenerSpec: local Person renamed to DirtyCheckPerson to avoid DuplicateMappingException with TCK
  • grails-test-examples/hibernate7: demo33 UniqueConstraintOnHasOneSpec @NotYetImplemented removed (test now passes); GormAdvancedSpec pagination fixed
  • grails-data-hibernate7-core GormApiAllocationSpec: verifies O(M+N) API count across single-datasource, multi-datasource, and multi-tenant configurations

Description

Contributor Checklist

Please review the following checklist before submitting your pull request. Pull requests that do not meet these requirements may be closed without review.

Issue and Scope

  • This PR is linked to an existing issue that has been acknowledged or approved by the project team. If no approved issue exists, please give background on why this change is necessary. Tickets are preferred for release change log history.
  • This PR addresses the complete scope of the linked issue. Partial implementations or unfinished work should not be submitted for review.
  • This PR contains a single, focused change. Unrelated changes should be submitted as separate pull requests.
  • This PR targets the correct branch for the type of change:
    • Patch release branches (e.g., 7.0.x): Bug fixes only. No new features or API changes.
    • Minor release branches (e.g., 7.1.x): New features are welcome, but breaking existing APIs must be avoided.
    • Major release branches (e.g., 8.0.x): Reserved for major changes. Breaking API changes are permitted.

Code Quality

  • I have added or updated tests that cover the changes introduced in this PR. All code contributions are expected to include appropriate test coverage.
  • I have verified that all existing tests pass by running ./gradlew build --rerun-tasks.
  • My code follows the project's code style guidelines. I have run ./gradlew codeStyle and resolved any violations. See Code Style for details.
  • This PR does not include mass reformatting, style-only changes, or large-scale refactoring unless it was explicitly approved in the linked issue. Unsolicited reformatting will not be accepted.
  • If generative AI tooling was used in preparing this contribution, a quality model was used to ensure contributions are consistent with the project's quality standards.

Licensing and Attribution

Documentation

  • If this PR introduces user-facing changes, I have included or updated the relevant documentation.
  • If this PR adds a new feature, I have updated the What's New section of the Grails Guide.
  • If this PR introduces breaking changes or changes that require user action during an upgrade, I have updated the Upgrade Notes for the corresponding version in the Grails Guide.
  • The PR description clearly explains what was changed and why.

First-time contributors: Please read our Contributing Guide before submitting.
Pull requests that appear to be auto-generated, incomplete, or unrelated to an approved issue may be
closed to help maintainers focus on reviewed and planned work. We appreciate your understanding.

…store init

Wires Hibernate 7 to the new GormRegistry with correct child datastore
initialization order, fixing the gaps that PR #15771 intentionally deferred:

- HibernateDatastore (H7): registers child datastores with GormRegistry eagerly
  during initialization, preserving schema/database/datasource routing
- HibernateGormInstanceApi: use getHibernateTemplate() lazy getter for
  isAttached(), lock(), and attach() — factory constructor leaves the field null
- HibernateGormStaticApi: executeQuery(query, Map) passes params as both named
  params and query settings so max/offset pagination is applied
- HibernateSession: coerceId() converts String IDs to the entity's declared
  identifier type in retrieveAll(), fixing String→Long lookup mismatch
- HibernateGormEnhancerSpec: updated to use GormRegistry public API
- HibernateDirtyCheckingSpec / HibernateUpdateFromListenerSpec: local Person
  renamed to DirtyCheckPerson to avoid DuplicateMappingException with TCK
- grails-test-examples/hibernate7: demo33 UniqueConstraintOnHasOneSpec
  @NotYetImplemented removed (test now passes); GormAdvancedSpec pagination fixed
- grails-data-hibernate7-core GormApiAllocationSpec: verifies O(M+N) API count
  across single-datasource, multi-datasource, and multi-tenant configurations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 26, 2026 21:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR advances the Hibernate 7 (GORM) O(M+N) scaling work by wiring Hibernate 7 into the shared GormRegistry, tightening multi-tenant / multi-datasource session handling, and adjusting query + pagination behavior to better match expected contracts across core, plugin, and TCK/test examples.

Changes:

  • Integrate Hibernate 7 datastores and GORM APIs with GormRegistry (including child datastore qualifier registration and updated API lookups in tests/examples).
  • Refine Hibernate 7 session/query behavior (ID coercion in bulk retrieval, HQL query wrappers/events, pagination result type updates).
  • Expand and update Hibernate 7 test coverage (scalability assertions, transaction/session lifecycle, multi-tenant and multi-datasource behavior).

Reviewed changes

Copilot reviewed 75 out of 75 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
grails-test-examples/hibernate7/grails-multitenant-multi-datasource/grails-app/services/example/MetricService.groovy Switch static API lookup to GormRegistry
grails-test-examples/hibernate7/grails-database-per-tenant/src/integration-test/groovy/example/DatabasePerTenantIntegrationSpec.groovy Remove console printing; keep logging
grails-test-examples/hibernate7/grails-database-per-tenant/grails-app/services/example/AnotherBookService.groovy Annotation order + flush on save
grails-test-examples/hibernate7/grails-database-per-tenant/grails-app/conf/logback.xml Increase logging verbosity for debugging
grails-test-examples/hibernate7/demo33/src/test/groovy/demo/UniqueConstraintOnHasOneSpec.groovy Remove @NotYetImplemented to enable test
grails-data-hibernate7/spring-orm/src/main/java/org/grails/orm/hibernate/support/hibernate7/HibernateTransactionManager.java Tx detection/logging + exception conversion changes
grails-data-hibernate7/ISSUES.md Add Hibernate 7 scaling/perf notes
grails-data-hibernate7/grails-plugin/src/test/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptorSpec.groovy Bind/unbind native session in test
grails-data-hibernate7/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java Use sessionFactory-aware OSIV readonly checks
grails-data-hibernate7/docs/build.gradle Pin jline dependency version
grails-data-hibernate7/core/src/test/resources/simplelogger.properties Add targeted test logger category
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/hibernate7/HibernateTransactionManagerSpec.groovy New unit coverage for tx manager behavior
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/support/ClosureEventListenerSpec.groovy Update listener construction signature
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/SchemaTenantGormEnhancerSpec.groovy Remove unused import
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/query/HqlQueryContextSpec.groovy Update expected default HQL aliasing
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateTenantContextProfilingSpec.groovy New profiling comparison for tenant wrapping
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateSessionSpec.groovy Add tests for native session fallback contract
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormValidationApiSpec.groovy Validate API retrieval via GormRegistry
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpec.groovy Static API via GormRegistry + paged list type update
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormInstanceApiSpec.groovy Instance API via GormRegistry
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormEnhancerSpec.groovy Enhancer tests updated to registry lookups
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateGormApiFactorySpec.groovy New unit test for API factory outputs
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/HibernateDatastoreIntegrationSpec.groovy Ensure leaked resources unbound in setup
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/GormRegistryScalabilitySpec.groovy New O(M+N) registry scalability assertions
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/WhereQueryMultiDataSourceSpec.groovy Adjust config key format for secondary DS
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/SingleTenantSpec.groovy Reset registries/resources to prevent leaks/flakes
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy Reset registries/resources + H2 DB close delay
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithEventsSpec.groovy Use connection-qualified GORM access in tx block
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/connections/DataServiceMultiDataSourceSpec.groovy Replace interpolated HQL with named params
grails-data-hibernate7/core/src/test/groovy/org/grails/orm/hibernate/ChildHibernateDatastoreUnitSpec.groovy Add SCHEMA child session contract tests
grails-data-hibernate7/core/src/test/groovy/org/grails/datastore/gorm/GormEnhancerCleanupSpec.groovy Update cleanup assertions to GormRegistry
grails-data-hibernate7/core/src/test/groovy/org/apache/grails/data/testing/tck/tests/PagedResultSpecHibernate.groovy Update expected paged list class name
grails-data-hibernate7/core/src/test/groovy/org/apache/grails/data/hibernate7/core/GrailsDataHibernate7TckManager.groovy Re-register enhancers after registry cleanup; improve teardown
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/WithNewSessionAndExistingTransactionSpec.groovy Stabilize connection-pool active-count assertions
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/validation/UniqueWithinGroupSpec.groovy Avoid duplicate insert; validate after clear
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/services/DataServiceSpec.groovy Replace interpolated HQL with named params
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/PagedResultListSpec.groovy Update paged list type assertions
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy Add coverage for conjunction/disjunction criteria behavior
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/HibernatePagedResultListSpec.groovy Rename/update paged list tests for new type
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy Expose typed transaction manager accessor
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateUpdateFromListenerSpec.groovy Rename entity fixture to avoid mapping collisions
grails-data-hibernate7/core/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy Rename entity fixture to avoid mapping collisions
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/TenantBoundHibernateTemplate.groovy New template to bind tenant during execution
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy Add insert-active thread-local marker + helpers
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/GormAutoTimestampFlushEntityEventListener.java New flush listener to timestamp before dirty-check
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java Improve state sync + simplify dirty tracking activation
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java Add deep-validation suppression + registry validation API lookup
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/SchemaTenantGormEnhancer.java Ensure parent/child datastore init order and qualifier wiring
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SelectHqlQuery.java Add paging wrapper + pre/post query events + count projection handling
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/PagedResultList.java New Hibernate 7 paged list implementation
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/JpaCriteriaQueryCreator.java Reuse predicate generator to reduce churn
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.java Build default HQL via list-query builder
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlListQueryBuilder.java Improve sort/order clause generation
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java Paging wrapper + conjunction/disjunction fixes + native session usage
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HibernateHqlQuery.java New wrapper query with pre/post query events
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/multitenancy/MultiTenantEventListener.java Replace enhancer lookups with registry resolver
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSessionResolver.groovy New resolver bridging GORM + native session bindings
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java Native session handling + bulk retrieval + query creation updates
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormValidationApi.groovy Add qualifier-aware API creation + lazy template access
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormInstanceApi.groovy Lazy template getter + deep-validate suppression + behavior alignment
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormEnhancer.groovy Register Hibernate API factory with GormRegistry
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormApiFactory.groovy New factory producing Hibernate-specific APIs
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateDatastore.java Child qualifier registration + session resolution + listener wiring
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTransactionManager.groovy Bind datastore resource + preferred datastore during tx
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java Improve executeWithNewSession resource unbinding/restore
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/event/listener/HibernateEventListener.java Construct ClosureEventListener with datastore reference
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/dirty/GrailsEntityDirtinessStrategy.groovy Use GormRegistry resolver + updated dirty-check logic
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/ChildHibernateDatastore.java Improve init, tx manager resolution, and native session binding
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java Filter entities per-connection + broaden entity annotation detection
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java Return concrete mapping factory + filter per datasource
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java Guard + handle Hibernate 7 contains() behavior
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/binder/GrailsDomainBinder.java Minor lambda style change in binding loop
grails-data-hibernate7/core/src/main/groovy/grails/orm/CriteriaMethodInvoker.java Use new PagedResultList type
grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy Route static API lookups via GormRegistry; add native SQL helpers

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to 39
<logger name="org.grails.orm.hibernate" level="debug" />
<logger name="grails.gorm.transactions" level="debug" />
<logger name="org.springframework.transaction" level="debug" />

<root level="debug">
<appender-ref ref="STDOUT" />
Comment on lines +119 to +123
public void disconnect() {
connected = false;
if (nativeSession != null && nativeSession.isOpen()) {
nativeSession.close();
}
Comment on lines +468 to +471
// Determine the unique set of keys for the HQL IN query
Collection<Object> uniqueKeys = new LinkedHashMap<Object, Object>() {{
for (Object k : inputKeys) { put(k, k); }
}}.keySet();
Comment on lines +443 to +452
private static Object coerceId(Object key, Class<?> idType) {
if (key == null || idType == null || idType.isInstance(key)) {
return key;
}
if (key instanceof String s) {
if (idType == Long.class) return Long.parseLong(s);
if (idType == Integer.class) return Integer.parseInt(s);
}
return key;
}
@testlens-app

testlens-app Bot commented Jun 27, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 14e6ca2
▶️ Tests: 480 executed
⚪️ Checks: 42/42 completed


Learn more about TestLens at testlens.app.

@borinquenkid

Copy link
Copy Markdown
Member Author

Superseded by the restructured feat/gorm-registry-h7 branch on top of the new per-adapter PR stack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants