From 5b6d775a849afc59227c55d6d692ca77ff88a2e1 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Thu, 25 Jun 2026 11:54:09 -0500 Subject: [PATCH 1/4] fix: align H7 HibernateGormStaticApi internal SQL method names with H5 Rename findWithNativeSql/findAllWithNativeSql to findWithSql/findAllWithSql in HibernateGormStaticApi so the Native suffix is not visible outside the implementation. HibernateEntity already exposes the correct public names; only the internal delegation calls are updated. Co-Authored-By: Claude Sonnet 4.6 --- .../groovy/grails/gorm/hibernate/HibernateEntity.groovy | 8 ++++---- .../grails/orm/hibernate/HibernateGormStaticApi.groovy | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy index edcdca57b87..66ddef4beb9 100644 --- a/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy +++ b/grails-data-hibernate7/core/src/main/groovy/grails/gorm/hibernate/HibernateEntity.groovy @@ -49,7 +49,7 @@ trait HibernateEntity extends GormEntity { */ @Generated static List findAllWithSql(CharSequence sql) { - currentHibernateStaticApi().findAllWithNativeSql(sql, Collections.emptyMap()) + currentHibernateStaticApi().findAllWithSql(sql, Collections.emptyMap()) } /** @@ -61,7 +61,7 @@ trait HibernateEntity extends GormEntity { */ @Generated static D findWithSql(CharSequence sql) { - currentHibernateStaticApi().findWithNativeSql(sql, Collections.emptyMap()) + currentHibernateStaticApi().findWithSql(sql, Collections.emptyMap()) } /** @@ -74,7 +74,7 @@ trait HibernateEntity extends GormEntity { */ @Generated static List findAllWithSql(CharSequence sql, Map args) { - currentHibernateStaticApi().findAllWithNativeSql(sql, args) + currentHibernateStaticApi().findAllWithSql(sql, args) } /** @@ -87,7 +87,7 @@ trait HibernateEntity extends GormEntity { */ @Generated static D findWithSql(CharSequence sql, Map args) { - currentHibernateStaticApi().findWithNativeSql(sql, args) + currentHibernateStaticApi().findWithSql(sql, args) } @Generated diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index b77b7e39c4e..d46ba7b9e3b 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -275,11 +275,11 @@ class HibernateGormStaticApi extends GormStaticApi { doListInternal(query, namedParams, [], args, false) } - D findWithNativeSql(CharSequence sql, Map args = Collections.emptyMap()) { + D findWithSql(CharSequence sql, Map args = Collections.emptyMap()) { doSingleInternal(sql, [:], [], args, true) as D } - List findAllWithNativeSql(CharSequence query, Map args = Collections.emptyMap()) { + List findAllWithSql(CharSequence query, Map args = Collections.emptyMap()) { doListInternal(query, [:], [], args, true) } From 92b2c98fa85ad5173cfaf2a18b50fac971eaa234 Mon Sep 17 00:00:00 2001 From: James Fredley Date: Fri, 26 Jun 2026 12:28:05 -0400 Subject: [PATCH 2/4] Align H7 SQL docs with historical API names Keep Hibernate 7 SQL helper documentation aligned with the historical Hibernate 5 GORM API names findWithSql and findAllWithSql. Remove the unreleased NativeSql method names from the H7 guide and keep the static API signature wording consistent. Assisted-by: opencode:openai/gpt-5.5 --- .../hibernate/HibernateGormStaticApi.groovy | 4 +- .../asciidoc/introduction/releaseHistory.adoc | 2 +- .../asciidoc/introduction/upgradeNotes.adoc | 9 ++-- .../src/docs/asciidoc/querying/nativeSql.adoc | 49 +++++++------------ 4 files changed, 24 insertions(+), 40 deletions(-) diff --git a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index d46ba7b9e3b..80b7ede2448 100644 --- a/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -279,8 +279,8 @@ class HibernateGormStaticApi extends GormStaticApi { doSingleInternal(sql, [:], [], args, true) as D } - List findAllWithSql(CharSequence query, Map args = Collections.emptyMap()) { - doListInternal(query, [:], [], args, true) + List findAllWithSql(CharSequence sql, Map args = Collections.emptyMap()) { + doListInternal(sql, [:], [], args, true) } // The single-argument CharSequence overloads accept a plain String (executed as written, as diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/releaseHistory.adoc b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/releaseHistory.adoc index 844854a941c..55b794ef201 100644 --- a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/releaseHistory.adoc +++ b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/releaseHistory.adoc @@ -29,7 +29,7 @@ Key features and changes relative to GORM for Hibernate 5: * **Hibernate ORM 7** — Full support for Hibernate 7, including Jakarta Persistence 3.2 and the Apache License 2.0. * **Spring Boot 4 / Spring Framework 7** — Grails {grailsMajorVersion} vendors the removed `org.springframework.orm.hibernate5` classes into `grails-data-hibernate7-spring-orm` under the `org.grails.orm.hibernate.support.hibernate7` package. * **HQL injection safety** — Single-argument `find`, `findAll`, `executeQuery`, and `executeUpdate` accept a plain `String` as on Hibernate 5; when a Groovy GString is passed, its `${value}` interpolations are bound as named parameters instead of being interpolated into the query text, so the idiomatic interpolated form is injection-safe by binding. -* **Native SQL queries** — New `findWithNativeSql` / `findAllWithNativeSql` methods added. +* **SQL query helpers** - `findWithSql` / `findAllWithSql` are available with the same names as Hibernate 5. * **Native query temporal types** — Native SQL queries return `java.time` types by default instead of legacy `java.sql` types. * **Removed deprecated Session API** — Hibernate's `save()`, `update()`, `delete()`, `load()`, and `get()` are replaced by JPA equivalents (`persist`, `merge`, `remove`, `getReference`, `find`). GORM's own dynamic methods are unaffected. * **`CascadeType.SAVE_UPDATE` removed** — GORM's ORM DSL `cascade: 'save-update'` string continues to work; direct use of the Hibernate `CascadeType` enum requires migration. diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc index 814a5e87db4..c5e103c7740 100644 --- a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc +++ b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc @@ -54,17 +54,14 @@ Book.executeQuery("from Book where title like ?1", [params.title + '%']) As in any ORM, manually concatenating untrusted input into a plain `String` (for example `"... where title = '" + userInput + "'"`) remains an injection risk and should be avoided in favour of the GString or parameterized forms above. -===== `findWithSql` / `findAllWithSql` renamed +===== SQL query helpers -`findWithSql` and `findAllWithSql` are deprecated. Use `findWithNativeSql` and `findAllWithNativeSql` instead. The old names remain as delegating aliases for backwards compatibility. +Hibernate 7 keeps the Hibernate 5 method names for raw SQL query helpers: [source,groovy] ---- -// Before (deprecated) +Book.findWithSql("select * from book where id = ${params.id}") Book.findAllWithSql("select * from book where ...") - -// After -Book.findAllWithNativeSql("select * from book where ...") ---- ==== Schema-per-Tenant — Schema Names Are Now Quoted diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc b/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc index eda1556714a..8445272fc59 100644 --- a/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc +++ b/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc @@ -18,11 +18,11 @@ under the License. //// [[querying-native-sql]] -== Native SQL Queries +== SQL Queries -GORM provides `findWithNativeSql` and `findAllWithNativeSql` for executing raw SQL when HQL or the Criteria API cannot express the query you need (e.g. database-specific functions, complex joins, or legacy SQL). +GORM provides `findWithSql` and `findAllWithSql` for executing raw SQL when HQL or the Criteria API cannot express the query you need (e.g. database-specific functions, complex joins, or legacy SQL). -WARNING: Native SQL bypasses Hibernate's type system and object mapping. Prefer HQL, the Criteria API, or dynamic finders wherever possible. Use native SQL only when there is no higher-level alternative. +WARNING: Raw SQL bypasses Hibernate's type system and object mapping. Prefer HQL, the Criteria API, or dynamic finders wherever possible. Use SQL only when there is no higher-level alternative. === Methods @@ -30,20 +30,20 @@ WARNING: Native SQL bypasses Hibernate's type system and object mapping. Prefer |=== | Method | Description -| `findWithNativeSql(CharSequence sql)` +| `findWithSql(CharSequence sql)` | Returns the first result mapped to the domain class -| `findWithNativeSql(CharSequence sql, Map args)` +| `findWithSql(CharSequence sql, Map args)` | Returns the first result; `args` controls pagination (`max`, `offset`, `cache`) -| `findAllWithNativeSql(CharSequence sql)` +| `findAllWithSql(CharSequence sql)` | Returns all results mapped to the domain class -| `findAllWithNativeSql(CharSequence sql, Map args)` +| `findAllWithSql(CharSequence sql, Map args)` | Returns all results; `args` controls pagination |=== -=== Safe Usage — GString Value Parameters +=== Safe Usage - GString Value Parameters When a query contains user-supplied **values** (not identifiers), use Groovy GString interpolation. GORM extracts each `${expression}` and binds it as a named JDBC parameter, preventing injection. @@ -51,8 +51,8 @@ When a query contains user-supplied **values** (not identifiers), use Groovy GSt ---- String nameFilter = params.name // user input -// ✅ SAFE — ${nameFilter} is bound as :p0, never inlined into the SQL string -List results = Club.findAllWithNativeSql( +// SAFE - ${nameFilter} is bound as :p0, never inlined into the SQL string +List results = Club.findAllWithSql( "select * from club c where c.name like ${nameFilter} order by c.name") ---- @@ -62,36 +62,23 @@ A plain `String` constant with no user data is safe and accepted directly. [source,groovy] ---- -// ✅ SAFE — no user input, static SQL -List results = Club.findAllWithNativeSql( +// SAFE - no user input, static SQL +List results = Club.findAllWithSql( "select * from club c order by c.name") ---- === What Cannot Be Parameterized -SQL identifiers — table names, column names, schema names — **cannot** be bound as JDBC parameters. Do not interpolate them from user input under any circumstances. +SQL identifiers - table names, column names, schema names - **cannot** be bound as JDBC parameters. Do not interpolate them from user input under any circumstances. [source,groovy] ---- -// ❌ UNSAFE — table name from user input, cannot be made safe via GString +// UNSAFE - table name from user input, cannot be made safe via GString String table = params.table -Club.findAllWithNativeSql("select * from ${table}") // DO NOT DO THIS +Club.findAllWithSql("select * from ${table}") // DO NOT DO THIS -// ❌ UNSAFE — string concatenation, no protection at all -Club.findAllWithNativeSql("select * from club where name = '" + userInput + "'") +// UNSAFE - string concatenation, no protection at all +Club.findAllWithSql("select * from club where name = '" + userInput + "'") ---- -If you need dynamic identifiers (e.g. schema-per-tenant), use the JDBC identifier quoting API (`connection.metaData.identifierQuoteString`) to quote and sanitize the name before use — the same mechanism used internally by `DefaultSchemaHandler`. - -=== Deprecated Names - -`findWithSql` and `findAllWithSql` are deprecated aliases for `findWithNativeSql` and `findAllWithNativeSql`. They remain functional for backwards compatibility but will be removed in a future release. - -[source,groovy] ----- -// Deprecated — replace with findAllWithNativeSql -Club.findAllWithSql("select * from club") - -// Preferred -Club.findAllWithNativeSql("select * from club") ----- +If you need dynamic identifiers (e.g. schema-per-tenant), use the JDBC identifier quoting API (`connection.metaData.identifierQuoteString`) to quote and sanitize the name before use - the same mechanism used internally by `DefaultSchemaHandler`. From e32142c1bcf5824b870608da32c5839b68844a54 Mon Sep 17 00:00:00 2001 From: Walter B Duque de Estrada Date: Fri, 26 Jun 2026 12:00:39 -0500 Subject: [PATCH 3/4] Update documentation to reference DetachedCriteria API --- .../docs/src/docs/asciidoc/querying/nativeSql.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc b/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc index 8445272fc59..420e60573db 100644 --- a/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc +++ b/grails-data-hibernate7/docs/src/docs/asciidoc/querying/nativeSql.adoc @@ -20,9 +20,9 @@ under the License. [[querying-native-sql]] == SQL Queries -GORM provides `findWithSql` and `findAllWithSql` for executing raw SQL when HQL or the Criteria API cannot express the query you need (e.g. database-specific functions, complex joins, or legacy SQL). +GORM provides `findWithSql` and `findAllWithSql` for executing raw SQL when HQL or the DetachedCriteria API cannot express the query you need (e.g. database-specific functions, complex joins, or legacy SQL). -WARNING: Raw SQL bypasses Hibernate's type system and object mapping. Prefer HQL, the Criteria API, or dynamic finders wherever possible. Use SQL only when there is no higher-level alternative. +WARNING: Raw SQL bypasses Hibernate's type system and object mapping. Prefer HQL, the DetachedCriteria API, or dynamic finders wherever possible. Use SQL only when there is no higher-level alternative. === Methods From 1e5799641cbd0260e828b0f00c72543a6ae8c7af Mon Sep 17 00:00:00 2001 From: Walter B Duque de Estrada Date: Fri, 26 Jun 2026 15:44:59 -0500 Subject: [PATCH 4/4] Update upgrade notes to remove outdated SQL helper methods Removed mention of Hibernate 5 method names for raw SQL query helpers. --- .../docs/src/docs/asciidoc/introduction/upgradeNotes.adoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc index c5e103c7740..2779e51e929 100644 --- a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc +++ b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction/upgradeNotes.adoc @@ -56,8 +56,6 @@ As in any ORM, manually concatenating untrusted input into a plain `String` (for ===== SQL query helpers -Hibernate 7 keeps the Hibernate 5 method names for raw SQL query helpers: - [source,groovy] ---- Book.findWithSql("select * from book where id = ${params.id}")