Hibernate 7 - Step 2 - #15568
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
04c43e8 to
f57b692
Compare
|
FYI: I added this comment due to the micronaut mismatches. I'll add a work around for this for now (no javadoc so it's probably ok to force api compatibility). Hopefully they update on the micronaut side so there aren't any issues. |
|
@borinquenkid can you take a look at that failure? |
|
@jdaugherty I created a local task not checked in and needed this setup to run relaibli sub.tasks.withType(Test).configureEach { t -> │ |
|
Still TODO:
|
|
@borinquenkid the latest round seems to have broken a lot of tests. Can you please take a look? I'd like to do another pass at this PR when you're done so we can actually review this functionality. |
1d767f9 to
848c778
Compare
|
I reset hard some of the changes because they touched core which affects other modules. GORM Scalability Analysis & Multi-Tenancy Risk Profile
Summary for June Release
|
|
TODO:
|
|
My bom changes are really separate from this review. They fix a critical mistake in 7.0.x - you have to still override the hibernate 5 version instead of just using the bom. I'm going to look at pulling those changes out of this review so that the review is focused on hibernate alone. |
|
This PR is currently blocked by #15605 Once that PR is merged, we will merge it up and then into this PR |
|
I need to split the micronaut bom into a hibernate5 & hibernate7 version as a next step. Will wait for this PR's latest round of tests to finish to see if anything else is missing. @borinquenkid Please note that I removed testcontainers bom from our bom - we're inheriting from Spring and that's being included. The validateDependencyVersions task ensures that our bom matches the versions being imported and Spring by default imports 2.0.5 (see https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-dependencies/4.0.6) |
|
FYI: I think I found out why testcontainers kept getting added to the boms - grails-forge is a micronaut app that still needs the older version. I've updated the micronaut dependencies to pull from the forge bom instead. |
|
I am not sure if you’ll be able to make the older jar work with the newer DockerWalterSent from my iPhoneOn May 3, 2026, at 3:52 PM, James Daugherty ***@***.***> wrote:jdaugherty left a comment (apache/grails-core#15568)
FYI: I think I found out why testcontainers kept getting added to the boms - grails-forge is a micronaut app that still needs the older version. I've updated the micronaut dependencies to pull from the forge bom instead.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
@borinquenkid FYI: the forge tests are passing with the changes. All of the grails projects are using the newer version from the spring bom. |
|
Cool. |
|
I split the micronaut bom into 2 - 1 for hibernate 5 & 1 for hibernate 7. Also, as part of the merge I lowered the memory back down and the tests are passing. At this point, I need to review the licensing for the liquibase-hibernate import & then we can review this PR. |
|
@borinquenkid I need your help - do you have a base branch of the liquibase library that you imported? I need to clearly know which files were brought into the project (we can't put our own headers on them). I'm assuming it's the files under: grails-data-hibernate7/dbmigration/src/main/java ? |
|
Per discussion with @borinquenkid 4.27 liquibase-hibernate is what was imported. This means: https://github.com/liquibase/liquibase-hibernate/tree/v4.27.0-hibernate5 is the branch |
- Rename snapshot/diff generators with 'Hibernate' prefix for clarity - Extract NoOpConnectionProvider and NoOpMultiTenantConnectionProvider from inner classes to standalone classes - Remove deprecated Hibernate 5 APIs: ClassLoaderDelegate, MetadataBuilderImpl, USE_NEW_ID_GENERATOR_MAPPINGS - Replace Class.newInstance() with Constructor.newInstance() reflection - Update Hibernate 7 API calls (MetadataBuilder, BootstrapServiceRegistry) - Update META-INF service files to match renamed classes - Update test fixtures for Hibernate 7 compatibility
|
I've reimported the code under dbmigration-core (dropping the liquibase name since it's trademarked). I've followed the guidelines here: https://www.apache.org/legal/src-headers.html#3party Which explicitly say do not add source headers. I've made 3 commits to illustrate the original forked code vs what Walter updated. I believe the licensing side of this is "right" now, but @jamesfredley do you think we should have someone in the ASF review this part of the contribution? |
Issue 1299 (grails-data-mapping) is about MongoDB configuration builder recursion and has no connection to this spec. The annotation was copied when the spec was ported between modules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… 5 to 7 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
We are working through your review comments against a deadline at the end of the month. Given the volume, using AI assistance is the only realistic way for me to address them at the speed and scale required. |
The belongsTo = [WqBiAuthor] edit was unnecessary scope-bleed in an H5 test file. Reverting to the original bare-class form belongsTo = WqBiAuthor restores the file to match 8.0.x and makes the H5 and H7 copies of the spec byte-for-byte identical again. Verified: spec passes 9/9. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the extra blank line between the package statement and imports - an unintentional formatting artifact. Restores the single-blank-line convention. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The license header was unintentionally reformatted (two-space to one-space indentation). Restore the canonical Apache header to match 8.0.x; the test changes in this file are unaffected. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The PR had inverted this spec's relationship from many-to-one to one-to-many and renamed the test, while the class kept its ...ManyToOne... name and the H7 twin kept the original many-to-one form. That changed what the test covers and broke H5/H7 symmetry. Reverting restores the original many-to-one semantics and re-aligns H5 with its H7 twin (modulo the H5/H7 sequence-param difference). Verified: spec passes 1/1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reviewers (mattias_reichel, paulk_asert, scott) flagged that checker-qual was added as an api dependency though only @NonNull/@nullable are used and no Checker analyzer runs, so it leaked a runtime dependency to all GORM consumers for zero benefit. JSpecify is already on the compile classpath via the Spring Boot 4 BOM (the Spring 7 ecosystem standard) and one binder already used it, so the module was mixing two nullness libraries. Standardize on JSpecify: - swap the four checker-qual imports to org.jspecify.annotations - drop 'api org.checkerframework:checker-qual'; add 'compileOnly org.jspecify:jspecify' - remove the now-unused checker-qual BOM entries (both PR-added, absent on 8.0.x) Compiles, checkstyle passes, binder specs green (83/83). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The HibernateGrailsPlugin grailsVersion still declared '7.0.0-SNAPSHOT > *' on the 8.0.x branch (projectVersion is 8.0.0-SNAPSHOT). Update both the H5 and H7 plugins to '8.0.0-SNAPSHOT > *' to match the branch and keep the two plugins consistent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per review feedback, the binder-wiring method is mostly an orchestrator: a long run of 'TypeName x = new TypeName(...)' declarations where the type is repeated verbatim on the right. Converting the 36 locals to var removes that redundant left-hand repetition and makes the wiring far easier to read. No behavior change (var is compile-time inference); compiles and checkstyle passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getCollector() compiles fine under the class-level @CompileStatic, so the method-level SKIP was unnecessary. Removed it (the method now inherits the class default). The SKIP on setupSpec() is left in place — that one genuinely needs it for the Spring bean-definition DSL. Verified: compiles and the plugin module tests pass (18/18). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The JSpecify migration removed the checker-qual dependency entirely, which broke compilation under JDK 25 (CI was green on JDK 21, red on JDK 25). JDK 25's javac requires checker-framework annotations such as @UnknownKeyFor — carried in the bytecode of dependencies like Hibernate's BytecodeProvider — to be resolvable on the compile classpath; JDK 21's javac tolerates them missing. Restore checker-qual as compileOnly (not api): it satisfies the compile-time annotation resolution JDK 25 needs without leaking a runtime dependency to GORM consumers, which was the original review concern. The JSpecify annotations on our own classes are kept. Verified under JDK 25 (Corretto 25.0.1): grails-data-hibernate7-core and all dependent H7 modules (grails-plugin, dbmigration, spring-orm, spring-boot) compile. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🚨 TestLens detected 1 failed test 🚨Here is what you can do:
Test SummaryCI - Groovy Joint Validation Build / build_grails > :grails-test-examples-scaffolding:integrationTest
🏷️ Commit: 7c2c442 Test FailuresUserControllerSpec > User list (:grails-test-examples-scaffolding:integrationTest in CI - Groovy Joint Validation Build / build_grails)Muted TestsSelect tests to mute in this pull request:
Reuse successful test results:
Click the checkbox to trigger a rerun:
Learn more about TestLens at testlens.app. |
matrei
left a comment
There was a problem hiding this comment.
Some more feedback, will continue.
| * Created by graemerocher on 01/03/2017. | ||
| */ | ||
| @Ignore | ||
| @Ignore // https://github.com/apache/grails-core/issues/14624 — MappingException: Repeated column (iteration_id) for Product; not fixed in this PR |
There was a problem hiding this comment.
- Use the
@Issueannotation instead of a comment. - "not fixed in this PR" can be removed.
There was a problem hiding this comment.
Done in 6505db22bb — class-level @Issue('https://github.com/apache/grails-core/issues/14624') added alongside @Ignore; the redundant method-level @Ignore // not yet implemented and the stale grails-data-mapping/issues/882 ref removed.
| import spock.lang.Issue | ||
|
|
||
| @Issue('https://github.com/apache/grails-data-mapping/issues/1299') |
There was a problem hiding this comment.
Leave a blank line between imports and class declaration?
There was a problem hiding this comment.
Done in 6505db22bb — blank line added in both H5 and H7.
There was a problem hiding this comment.
Have you pushed 6505db22bb?
| * TODO: rename to AHibernateSpec to follow the abstract class naming convention | ||
| * |
There was a problem hiding this comment.
I don't think it is a good idea to rename it to AHibernateSpec.
There was a problem hiding this comment.
Agreed — TODO removed in 6505db22bb.
There was a problem hiding this comment.
I cannot see that the TODO was removed.
There was a problem hiding this comment.
I do disagree. By deprecating the current methods (findWithSql, findAllWithSql), and delegating to new methods (findWithNativeSql, findAllWithNativeSql), you are effectively changing the public API of GORM without discussion and consensus.
Also, please don't mark my review comments as resolved as it makes it very hard to find them.
- JSpecify: replace jakarta.annotation.Nonnull with org.jspecify.annotations.NonNull in ClassBinder, ClassPropertiesBinder, CollectionForPropertyConfigBinder, ColumnConfigToColumnBinder, ComponentBinder, RootBinder, SimpleValueBinder - @SInCE 8.0: add to ClassBinder, CollectionBinder, CollectionForPropertyConfigBinder, ColumnBinder, ColumnConfigToColumnBinder, ComponentBinder - @author: remove from GrailsBytecodeProvider, ClassPropertiesBinder, HibernateCriteriaBuilder - ClassPropertiesBinder: fix @SInCE 7.0 → 8.0; remove constructor Javadoc descriptions - ClassBinder: improve class Javadoc; fix persistant → persistent typo - CollectionBinder: add @SInCE 8.0; remove constructor Javadoc description; use var - ColumnBinder: fix stale [GrailsDomainBinder] prefix in log messages - ColumnConfigToColumnBinder: remove dialect-aware default precision logic — only apply explicitly configured values; dialect defaults belong in NumericColumnConstraintsBinder - SimpleValueBinder/ColumnBinder: wire actual Dialect from JdbcEnvironment through to NumericColumnConstraintsBinder so Oracle precision (126) is applied correctly at runtime - HibernateCriteriaBuilder: fix run-on Architecture Javadoc sentence; document both setCriteriaMethodInvoker() and subclassing as extension points - ColumnConfigToColumnBinderSpec: update tests to reflect that precision/scale are not set when unspecified (no longer defaulted to 15) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- SubclassMultipleListCollectionSpec (H5+H7): replace inline @ignore comment with @issue('#14624') annotation at class level; move @issue to test method; remove stale grails-data-mapping/issues/882 ref - PersistentPropertySpec (H5+H7): add blank line between imports and class declaration - HibernateSpec (H7): remove TODO suggesting rename to AHibernateSpec Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…bernateEntity Clean-break rename agreed in weekly meeting: HibernateEntity (H7) now exposes only withSql(CharSequence) / withSql(CharSequence, Map) and withAllSql(CharSequence) / withAllSql(CharSequence, Map). The old findWithNativeSql / findAllWithNativeSql primary methods and the deprecated findWithSql / findAllWithSql aliases are all removed from the trait and from HibernateGormStaticApi (H7). In H5 the new withSql/withAllSql methods are added and the existing findWithSql / findAllWithSql methods are deprecated pointing to the new names; this keeps H5 backward-compatible while aligning the public API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
H7 HibernateEntity now adds withSql/withAllSql alongside the existing findWithNativeSql/findAllWithNativeSql and deprecated findWithSql/findAllWithSql methods — no removal of existing methods. The new methods use the same private helper pattern as H5 (currentHibernateStaticApi()) instead of inline casting. H5 HibernateEntity is reverted to its original state — no new methods, no deprecation annotations added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The withSql/withAllSql additions are reverted. H7 HibernateEntity now exposes exactly what it had before: findWithNativeSql/findAllWithNativeSql as the primary methods and deprecated findWithSql/findAllWithSql as backward-compat aliases, all delegating through the private currentHibernateStaticApi() helper. Tests updated to use findWithNativeSql/findAllWithNativeSql and findWithSql/findAllWithSql accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
H7's HibernateEntity now exposes the same public method names as H5 (findWithSql / findAllWithSql) while delegating internally to HibernateGormStaticApi.findWithNativeSql / findAllWithNativeSql. No deprecated aliases, no findWithNativeSql on the trait surface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These aliases are no longer needed: the HibernateEntity trait now exposes findWithSql/findAllWithSql directly, delegating to findWithNativeSql/ findAllWithNativeSql which remain the implementation in HibernateGormStaticApi. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reorder JSpecify imports in the Hibernate 7 binder classes and restore the ColumnConfigToColumnBinder license header indentation so grails-data-hibernate7-core Checkstyle passes. Assisted-by: Hephaestus:openai/gpt-5.5

Hibernate 7.4 Breaking Changes (Application Migration)
These are the Hibernate 7.4 behaviours that differ from Hibernate 5.6 and remain the application owner's responsibility when migrating from the Hibernate 5 plugin to Hibernate 7. GORM-facing issues that this PR already resolves are intentionally omitted - only the breaking changes that survive are listed.
grails-data-hibernate5, H5 BOM constraints, or H5-only transitive dependencies with the H7 runtime can fail dependency resolution or application boot.findWhereorfindAllWherenow fails fast.lock: trueis used.QueryTimeoutExceptionorLockTimeoutExceptionfor query and lock timeout paths.PersistenceExceptionwhen the database marks the transaction for rollback.PersistenceExceptionaround direct Hibernate/JPA timeout-sensitive code and inspect the cause when necessary.java.sqltemporal values.java.timetemporal values by default.java.sql.Date,Time, orTimestamp.java.timetypes, or sethibernate.query.native.prefer_jdbc_datetime_types=trueduring migration.not nullby default.@Versioncolumnsnot nullby default.dbCreate=update, especially for legacy nullable version columns.char/Character, Oracle floating point,@ElementCollectionsets,@CreationTimestamp,@UpdateTimestamp, and Oracle 23c LOB columns.import.sqlimport.sqlon the classpath can run where it was previously ignored.import.sqlfiles from the runtime classpath or make schema-generation settings explicit.hibernate.max_fetch_depth=2default.hibernate.max_fetch_depthexplicitly if the application relies on that behavior.max/offsetor limits with collection fetch joins can return a different row/window shape.org.hibernate.limitInMemoryquery hint only when the previous in-memory behavior is required.current dateandlocal datecould preserve a time component because Oracle has no true date-only function.trunc(current_date).current dateorlocal dateand change the expression if a timestamp is required.@Anymappings@Anymappings were loaded by a separate select.@Anyassociations when loading an entity by id.@Anymappings can produce different SQL shape and row width.@Anymappings for performance and row duplication implications.hibernate-community-dialectsunderorg.hibernate.community.dialect.hibernate-coreunderorg.hibernate.dialect.org.hibernate.dialect.SpannerPostgreSQLDialector rely on automatic dialect resolution.NOT_AUDITEDassociationsNOT_AUDITEDwas requested.RelationTargetAuditMode.NOT_AUDITED.RelationTargetAuditMode.NOT_AUDITED.HibernateDatastoresetup can miss domain or service classes if the scanned package is wrong.Reopening. This PR replaces #15530
Please note that I split off a prerequisite PR #15654
This allows us to better see what changed between hibernate 5 & 7 - otherwise the hibernate 7 code looks like it was just added instead of changed. Commit a47d8cb is the original commit prior to this split if we need to compare this branch to that for any reason (mistakes, etc).