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

   > **Depends on #16351** (the Java-to-Groovy migration): this branch is based 
on `9.0.x-java-to-groovy`, so until #16351 merges the diff shown here includes 
it. Once it merges, the diff shrinks to the 127 commits of this PR. Opened as a 
draft for that reason. The two follow-ups are stacked on it: native binding as 
the default, then the deletion of the classic binder.
   
   ## What
   
   GORM for Hibernate 7 gains **native domain binding**: a 
`GrailsDomainGenerator` turns an already-built GORM `PersistentEntity` into a 
JPA/Hibernate-annotated carrier class, and Hibernate's own annotation binder 
binds it. Sessions, queries and proxies keep using the real domain classes (the 
carrier's entity name, cache regions and class-loader lookups all resolve to 
the real class). In this PR it is **opt-in** 
(`hibernate.generatedDomainClasses: true`); the next PR in the stack makes it 
the default, and the last one deletes the hand-built `GrailsDomainBinder`.
   
   ## Why
   
   The classic binder re-implements Hibernate's boot model by hand (~5,800 
lines) and has been the source of a steady stream of mapping defects (seven of 
them fixed on `8.0.x` during this work: #16520, #16522, #16523, #16524, #16531, 
#16532, #16533, #16539). Letting Hibernate bind the entities removes that 
layer; the GORM mapping DSL stays the public surface.
   
   ## Scope
   
   * `grails-data-hibernate7/core`, package 
`org.grails.orm.hibernate.cfg.domainbinding.jpa`: `GrailsDomainGenerator` 
(ByteBuddy; every mapping option the classic binder honours, incl. composite 
identifiers via `@IdClass`, embedded types, all three inheritance strategies, 
multi-tenancy, natural ids, caches, custom and converting types, custom 
collection types), `GeneratedDomainClassBinder` (`AdditionalMappingContributor` 
plus an aligner that reproduces the classic binder's naming and DDL decisions 
where Hibernate's defaults differ), `GeneratedDomainClassLoader[Service]`.
   * `ManyToManyOwnerValidator`: a bidirectional many-to-many with `belongsTo` 
on neither side now **fails at startup** (`MappingException`) instead of 
silently never being written; on `8.0.x` the same case logs a warning (#16532).
   * Envers: a generated entity carries a JPA `@Version`, which Envers would 
skip; the optimistic-lock column is audited as before unless the application 
sets `org.hibernate.envers.do_not_audit_optimistic_locking_field` itself.
   * Tests: 26 both-modes specs under `grails.gorm.tests.generated`, the whole 
core suite runnable through the generated classes 
(`-Pgrails.test.generatedDomainClasses=true`), and two differentials that 
compare native binding with the classic binder over every scanned test domain 
class (1,169 entities, 3,381 properties: **0 mismatches**; DDL: **85 known 
differences, 0 unknown, 0 refused**). The classic side of both differentials is 
**frozen** as recorded data (`src/test/resources/classic-oracle/`), so they 
survive the deletion of the classic binder.
   * Docs: new chapter *Native Domain Binding* in the GORM for Hibernate 7 
manual (what stays the same, what changes in behaviour and schema, switching an 
existing database, Envers, the one unsupported mapping and its workaround), 
configuration reference, Hibernate 7 migration checklist, and the Grails 8 → 9 
upgrade notes (`upgrading90x.adoc` §1).
   
   Also in this PR, because the branch has to pass the repository's CodeNarc 
rules: the `grails-startup-progress` sources that arrived from upstream in Java 
are converted to Groovy, and intentionally empty catch parameters are named 
`ignored` in seven modules.
   
   ## Behaviour changes for applications (all documented in the upgrade notes)
   
   * A many-to-many without an owning side fails at startup.
   * With native binding on: a custom `UserCollectionType` on a `hasMany` of 
entities takes effect (the classic binder ignored it); a shared embedded 
collection gets a table per owner; an embedded object as a part of a composite 
identifier is refused with a message pointing at the documented flattening 
workaround; a handful of schema differences listed in the manual (for example 
`check (idx >= 0)` on list index columns).
   
   ## Verification
   
   Every module of `grails-data-hibernate7` in both modes at the tip of this 
PR: core 4,813 tests (classic default) and 4,523 (generated), dbmigration-core 
40, dbmigration 110 + 93 CLI, plugin 39 + 2, spring-boot 2, all green; both 
differentials as above; `codeStyle` clean; docs built.
   
   🤖 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: [email protected]

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

Reply via email to