This is an automated email from the ASF dual-hosted git repository.

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 16f87ae438b4b60acc1842dab48d134f7ae2edbc
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Tue Mar 3 17:50:25 2026 -0600

    updated docs using Copilot
---
 .../src/docs/asciidoc/advancedGORMFeatures.adoc    |  36 ++++++
 .../advancedGORMFeatures/defaultSortOrder.adoc     |  43 +++++++
 .../docs/asciidoc/advancedGORMFeatures/ormdsl.adoc |  19 ++++
 .../advancedGORMFeatures/ormdsl/caching.adoc       |  95 ++++++++++++++++
 .../ormdsl/compositePrimaryKeys.adoc               |  49 ++++++++
 .../ormdsl/customCascadeBehaviour.adoc             |  50 +++++++++
 .../ormdsl/customHibernateTypes.adoc               |  67 +++++++++++
 .../ormdsl/customNamingStrategy.adoc               |  52 +++++++++
 .../ormdsl/databaseIndices.adoc                    |  55 +++++++++
 .../ormdsl/derivedProperties.adoc                  |  57 ++++++++++
 .../advancedGORMFeatures/ormdsl/fetchingDSL.adoc   |  74 +++++++++++++
 .../advancedGORMFeatures/ormdsl/identity.adoc      |  65 +++++++++++
 .../ormdsl/inheritanceStrategies.adoc              |  95 ++++++++++++++++
 .../ormdsl/optimisticLockingAndVersioning.adoc     |  65 +++++++++++
 .../ormdsl/tableAndColumnNames.adoc                | 123 +++++++++++++++++++++
 .../docs/src/docs/asciidoc/domainClasses.adoc      |  66 +++++++++++
 .../asciidoc/domainClasses/gormAssociation.adoc    |  28 +++++
 .../gormAssociation/basicCollectionTypes.adoc      |  88 +++++++++++++++
 .../domainClasses/gormAssociation/manyToMany.adoc  |  68 ++++++++++++
 .../gormAssociation/manyToOneAndOneToOne.adoc      |  78 +++++++++++++
 .../domainClasses/gormAssociation/oneToMany.adoc   |  71 ++++++++++++
 .../asciidoc/domainClasses/gormComposition.adoc    |  61 ++++++++++
 .../asciidoc/domainClasses/inheritanceInGORM.adoc  |  54 +++++++++
 .../asciidoc/domainClasses/sets,ListsAndMaps.adoc  |  69 ++++++++++++
 .../docs/src/docs/asciidoc/introduction.adoc       |  53 +++++++++
 .../docs/src/docs/asciidoc/persistenceBasics.adoc  |   4 +
 .../docs/asciidoc/persistenceBasics/cascades.adoc  |  44 ++++++++
 .../persistenceBasics/deletingObjects.adoc         |  53 +++++++++
 .../docs/asciidoc/persistenceBasics/fetching.adoc  |  55 +++++++++
 .../docs/asciidoc/persistenceBasics/locking.adoc   |  40 +++++++
 .../persistenceBasics/modificationChecking.adoc    |  45 ++++++++
 .../persistenceBasics/savingAndUpdating.adoc       |  76 +++++++++++++
 .../docs/asciidoc/programmaticTransactions.adoc    |  73 ++++++++++++
 .../docs/src/docs/asciidoc/querying.adoc           |  39 +++++++
 .../docs/src/docs/asciidoc/quickStartGuide.adoc    |   7 ++
 .../docs/asciidoc/quickStartGuide/basicCRUD.adoc   |  89 +++++++++++++++
 36 files changed, 2106 insertions(+)

diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures.adoc
index e69de29bb2..c7462361d0 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures.adoc
@@ -0,0 +1,36 @@
+[[advancedGORMFeatures]]
+== Advanced GORM Features
+
+This section covers advanced GORM and Hibernate mapping capabilities available 
through the `static mapping {}` DSL and other configuration mechanisms.
+
+The ORM DSL `mapping` block is available on every domain class and allows you 
to customise every aspect of the Hibernate mapping:
+
+[source,groovy]
+----
+class Book {
+    String title
+    Date dateCreated
+
+    static mapping = {
+        table     'books'
+        title     column: 'book_title', index: true
+        batchSize 20
+        cache     usage: 'read-write'
+    }
+}
+----
+
+The following topics are covered in this section:
+
+* xref:ormdsl-tableAndColumnNames[Table and Column Names]
+* xref:ormdsl-identity[Identity]
+* xref:ormdsl-compositePrimaryKeys[Composite Primary Keys]
+* xref:ormdsl-optimisticLockingAndVersioning[Optimistic Locking and Versioning]
+* xref:ormdsl-inheritanceStrategies[Inheritance Strategies]
+* xref:ormdsl-fetchingDSL[Fetching Strategies]
+* xref:ormdsl-caching[Caching]
+* xref:ormdsl-customCascadeBehaviour[Custom Cascade Behaviour]
+* xref:ormdsl-customNamingStrategy[Custom Naming Strategy]
+* xref:ormdsl-customHibernateTypes[Custom Hibernate Types]
+* xref:ormdsl-derivedProperties[Derived Properties]
+* xref:ormdsl-databaseIndices[Database Indices]
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/defaultSortOrder.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/defaultSortOrder.adoc
index e69de29bb2..f225b32f17 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/defaultSortOrder.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/defaultSortOrder.adoc
@@ -0,0 +1,43 @@
+[[advancedGORMFeatures-defaultSortOrder]]
+== Default Sort Order
+
+You can configure a default sort order for `list()` and `findAll*` queries at 
the domain class level using the `mapping` block:
+
+[source,groovy]
+----
+class Book {
+    String title
+    Date dateCreated
+
+    static mapping = {
+        sort 'title'            // <1>
+    }
+}
+----
+<1> All `Book.list()` calls will return results sorted by `title` in ascending 
order by default.
+
+=== Sort Direction
+
+[source,groovy]
+----
+static mapping = {
+    sort title: 'desc'          // <1>
+}
+----
+<1> Sort by `title` descending.
+
+=== Default Sort on Associations
+
+You can also define a default sort order on a `hasMany` collection:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books sort: 'title', order: 'asc'
+    }
+}
+----
+
+NOTE: The default sort order in `mapping` applies to queries that do not 
specify their own `order`. Any query that specifies `sort` or `order` 
explicitly will override the default.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl.adoc
index e69de29bb2..5248242564 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl.adoc
@@ -0,0 +1,19 @@
+[[advancedGORMFeatures-ormdsl]]
+== ORM DSL
+
+The ORM DSL is a `static mapping` closure on every domain class that gives you 
fine-grained control over how GORM maps your domain model to the database 
schema.
+
+See the subsections below for details on each feature:
+
+* xref:ormdsl-tableAndColumnNames[Table and Column Names]
+* xref:ormdsl-identity[Identity]
+* xref:ormdsl-compositePrimaryKeys[Composite Primary Keys]
+* xref:ormdsl-optimisticLockingAndVersioning[Optimistic Locking and Versioning]
+* xref:ormdsl-inheritanceStrategies[Inheritance Strategies]
+* xref:ormdsl-fetchingDSL[Fetching Strategies]
+* xref:ormdsl-caching[Caching]
+* xref:ormdsl-customCascadeBehaviour[Custom Cascade Behaviour]
+* xref:ormdsl-customNamingStrategy[Custom Naming Strategy]
+* xref:ormdsl-customHibernateTypes[Custom Hibernate Types]
+* xref:ormdsl-derivedProperties[Derived Properties]
+* xref:ormdsl-databaseIndices[Database Indices]
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/caching.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/caching.adoc
index e69de29bb2..49b95dc216 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/caching.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/caching.adoc
@@ -0,0 +1,95 @@
+[[ormdsl-caching]]
+== Caching
+
+GORM supports Hibernate's second-level cache and query cache. Caching is 
configured per domain class and optionally per association.
+
+=== Enabling Second-Level Cache
+
+Second-level cache is enabled globally via configuration:
+
+[source,yaml]
+----
+hibernate:
+    use_second_level_cache: true
+    cache:
+        region:
+            factory_class: 
'org.hibernate.cache.jcache.internal.JCacheRegionFactory'
+----
+
+Then enable caching for individual domain classes using the `cache` directive 
in the `mapping` block:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        cache true          // <1>
+    }
+}
+----
+<1> Enables the second-level cache for `Book` with the default `read-write` 
usage.
+
+=== Cache Usage
+
+You can control the cache usage strategy:
+
+[source,groovy]
+----
+static mapping = {
+    cache usage: 'read-only'    // <1>
+}
+----
+
+[format="csv", options="header"]
+|===
+usage,description
+`read-write`,Cached data can be read and written — default
+`read-only`,Cached data is never modified (best performance for immutable data)
+`nonstrict-read-write`,No strict locking; possible stale reads between updates
+`transactional`,Full transaction support (requires a JTA transaction manager)
+|===
+
+=== Cache Include
+
+The `include` option controls what data to cache:
+
+[source,groovy]
+----
+static mapping = {
+    cache usage: 'read-write', include: 'non-lazy'  // <1>
+}
+----
+<1> Only non-lazy properties are cached. Use `all` (default) to include lazy 
properties too.
+
+=== Caching Associations
+
+You can cache collection associations independently:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    static mapping = {
+        books cache: true
+    }
+}
+----
+
+=== Query Cache
+
+To cache the results of individual queries, pass `cache: true` in the query 
options and enable the query cache globally:
+
+[source,yaml]
+----
+hibernate:
+    cache:
+        use_query_cache: true
+----
+
+[source,groovy]
+----
+List<Book> books = Book.findAllByGenre('Fiction', [cache: true])
+----
+
+TIP: Only use the query cache for queries whose results change infrequently. 
Cached queries are invalidated whenever any entity in the queried table is 
updated.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/compositePrimaryKeys.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/compositePrimaryKeys.adoc
index e69de29bb2..198379629d 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/compositePrimaryKeys.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/compositePrimaryKeys.adoc
@@ -0,0 +1,49 @@
+[[ormdsl-compositePrimaryKeys]]
+== Composite Primary Keys
+
+GORM allows you to map domain classes to tables that use a composite primary 
key (a key composed of two or more columns). This is commonly needed when 
mapping to legacy database schemas.
+
+=== Defining a Composite Identity
+
+Use `id composite: [...]` in the `mapping` block, listing the property names 
that together form the primary key:
+
+[source,groovy]
+----
+class OrderItem {
+    Long orderId
+    Long productId
+    Integer quantity
+
+    static mapping = {
+        id composite: ['orderId', 'productId']  // <1>
+    }
+}
+----
+<1> The composite key is made up of `orderId` and `productId`.
+
+NOTE: Domain classes with composite keys do **not** have the auto-generated 
`id` and `version` properties. You are responsible for setting the key 
properties before calling `save()`.
+
+=== Using Composite Keys
+
+[source,groovy]
+----
+def item = new OrderItem(orderId: 1L, productId: 42L, quantity: 3)
+item.save()
+
+// Load by composite key — pass a map
+def found = OrderItem.get(orderId: 1L, productId: 42L)
+----
+
+=== Associations with Composite Keys
+
+When another domain class references a domain class with a composite key, GORM 
creates multiple foreign-key columns automatically:
+
+[source,groovy]
+----
+class OrderLine {
+    Integer lineNumber
+    OrderItem item     // foreign key will use both orderId and productId 
columns
+}
+----
+
+TIP: Composite primary keys add complexity to all queries and associations. 
Prefer surrogate (auto-generated) single-column keys wherever possible and use 
composite unique constraints instead of composite keys for business-key 
uniqueness requirements.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customCascadeBehaviour.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customCascadeBehaviour.adoc
index e69de29bb2..d5ca3cc55a 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customCascadeBehaviour.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customCascadeBehaviour.adoc
@@ -0,0 +1,50 @@
+[[ormdsl-customCascadeBehaviour]]
+== Custom Cascade Behaviour
+
+Hibernate cascades control which persistence operations (save, update, delete, 
etc.) are automatically propagated from a parent entity to its associated 
children.
+
+=== Default Cascade Behaviour
+
+By default GORM applies `save-update` cascading on associations — when you 
save or update an entity, changes to its associated objects are also persisted. 
Deletions are **not** cascaded by default.
+
+=== Configuring Cascade
+
+Use the `cascade` option in the `mapping` block to override the default:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    static mapping = {
+        books cascade: 'all'        // <1>
+    }
+}
+----
+<1> `all` cascades all operations including delete to `books`.
+
+[format="csv", options="header"]
+|===
+value,description
+`all`,Propagates all operations (save/update/delete/merge/refresh)
+`save-update`,Propagates save and update — default
+`delete`,Propagates delete only
+`all-delete-orphan`,Like `all` but also deletes child rows not present in the 
collection
+`none`,No cascade
+|===
+
+=== Cascade Delete Example
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    static mapping = {
+        books cascade: 'all-delete-orphan'  // <1>
+    }
+}
+----
+<1> When you remove a `Book` from `author.books` and call `author.save()`, the 
removed `Book` row is also deleted from the database.
+
+TIP: Use `all-delete-orphan` when the child entity has no meaning outside the 
parent (composition). Use `save-update` (default) when the child may belong to 
multiple parents (aggregation).
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customHibernateTypes.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customHibernateTypes.adoc
index e69de29bb2..79f709ba32 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customHibernateTypes.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customHibernateTypes.adoc
@@ -0,0 +1,67 @@
+[[ormdsl-customHibernateTypes]]
+== Custom Hibernate Types
+
+GORM allows you to map properties to custom Hibernate `UserType` 
implementations. This is useful for persisting non-standard Java/Groovy types — 
for example, storing a `List` as a comma-separated string, or encrypting values 
at the persistence layer.
+
+=== Per-Property Type
+
+Use the `type` option in the `mapping` block to assign a custom Hibernate type 
to a specific property:
+
+[source,groovy]
+----
+class Setting {
+    String name
+    Serializable value
+
+    static mapping = {
+        value type: 'serializable'      // <1>
+    }
+}
+----
+<1> The type name can be a Hibernate built-in type alias, a fully qualified 
class name, or a `Class` object.
+
+With a custom `UserType` class:
+
+[source,groovy]
+----
+class Product {
+    String name
+    List<String> tags
+
+    static mapping = {
+        tags type: CsvStringListType     // <1>
+    }
+}
+----
+<1> `CsvStringListType` implements `org.hibernate.usertype.UserType` and 
handles conversion between a comma-separated column value and a `List<String>`.
+
+=== Type Parameters
+
+If your custom type implements `org.hibernate.usertype.ParameterizedType`, 
pass parameters using `typeParams`:
+
+[source,groovy]
+----
+class Measurement {
+    BigDecimal value
+
+    static mapping = {
+        value type: FixedScaleDecimalType, typeParams: [scale: '4']
+    }
+}
+----
+
+=== Global User Type Mapping
+
+Register a user type for a given Java class globally so it applies to all 
properties of that type without explicit per-property configuration:
+
+[source,groovy]
+----
+class MyDomainClass {
+    static mapping = {
+        userTypes Money: MoneyUserType      // <1>
+    }
+}
+----
+<1> Any property of type `Money` in this class will use `MoneyUserType`.
+
+TIP: Implementing `org.hibernate.usertype.UserType` requires handling 
`sqlTypes()`, `nullSafeGet()`, `nullSafeSet()`, `deepCopy()`, and `equals()`. 
Prefer Hibernate's `CompositeUserType` for multi-column mappings.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customNamingStrategy.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customNamingStrategy.adoc
index e69de29bb2..0e0da62454 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customNamingStrategy.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/customNamingStrategy.adoc
@@ -0,0 +1,52 @@
+[[ormdsl-customNamingStrategy]]
+== Custom Naming Strategy
+
+By default GORM uses Hibernate's snake_case physical naming strategy 
(`PhysicalNamingStrategySnakeCaseImpl`), which converts camelCase class and 
property names to `snake_case` table and column names (e.g., `BookAuthor` → 
`book_author`, `firstName` → `first_name`).
+
+=== Configuring a Custom Strategy
+
+You can replace this with any Hibernate `PhysicalNamingStrategy` 
implementation via application configuration:
+
+[source,yaml]
+----
+hibernate:
+    physicalNamingStrategy: com.example.MyCustomNamingStrategy
+----
+
+Or set it per datasource:
+
+[source,yaml]
+----
+dataSources:
+    reporting:
+        hibernate:
+            physicalNamingStrategy: com.example.LegacyNamingStrategy
+----
+
+=== Implementing a Custom Strategy
+
+Implement Hibernate's `org.hibernate.boot.model.naming.PhysicalNamingStrategy` 
interface:
+
+[source,groovy]
+----
+import org.hibernate.boot.model.naming.Identifier
+import org.hibernate.boot.model.naming.PhysicalNamingStrategy
+import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment
+
+class UpperCaseNamingStrategy implements PhysicalNamingStrategy {
+
+    @Override
+    Identifier toPhysicalTableName(Identifier name, JdbcEnvironment 
jdbcEnvironment) {
+        return Identifier.toIdentifier(name.text.toUpperCase())
+    }
+
+    @Override
+    Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment 
jdbcEnvironment) {
+        return Identifier.toIdentifier(name.text.toUpperCase())
+    }
+
+    // ... other required method overrides ...
+}
+----
+
+TIP: Individual column or table names set explicitly in the `mapping` block 
always take precedence over what the naming strategy would produce.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/databaseIndices.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/databaseIndices.adoc
index e69de29bb2..9772224c6e 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/databaseIndices.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/databaseIndices.adoc
@@ -0,0 +1,55 @@
+[[ormdsl-databaseIndices]]
+== Database Indices
+
+GORM lets you define database indices on domain class columns directly in the 
`mapping` block, so they are created automatically when `hbm2ddl` generates the 
schema.
+
+=== Single-Column Index
+
+Set `index: true` on a column to create an auto-named index, or provide a 
string name to name it explicitly:
+
+[source,groovy]
+----
+class Book {
+    String title
+    String isbn
+    static mapping = {
+        title  index: true          // <1>
+        isbn   index: 'isbn_idx'    // <2>
+    }
+}
+----
+<1> Creates an unnamed (auto-named) index on `title`.
+<2> Creates a named index `isbn_idx` on `isbn`.
+
+=== Composite Index
+
+To create a composite index across multiple columns, use the same index name 
on each column:
+
+[source,groovy]
+----
+class OrderItem {
+    Long orderId
+    Long productId
+    static mapping = {
+        orderId   index: 'order_product_idx'    // <1>
+        productId index: 'order_product_idx'    // <1>
+    }
+}
+----
+<1> Both columns share the same index name, so Hibernate creates a single 
composite index.
+
+=== Unique Index
+
+You can combine `index` with `unique` to create a unique index:
+
+[source,groovy]
+----
+class Book {
+    String isbn
+    static mapping = {
+        isbn unique: true, index: 'isbn_unique_idx'
+    }
+}
+----
+
+NOTE: Indices are only created automatically when `hibernate.hbm2ddl.auto` is 
set to `create`, `create-drop`, or `update`. For production schemas, prefer 
explicit DDL migration scripts.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/derivedProperties.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/derivedProperties.adoc
index e69de29bb2..1b826050ba 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/derivedProperties.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/derivedProperties.adoc
@@ -0,0 +1,57 @@
+[[ormdsl-derivedProperties]]
+== Derived Properties
+
+A derived property is a read-only property whose value is computed by a SQL 
formula rather than stored in a dedicated column.
+
+=== Defining a Derived Property
+
+Use the `formula` option in the `mapping` block:
+
+[source,groovy]
+----
+class Order {
+    BigDecimal subtotal
+    BigDecimal taxRate
+
+    BigDecimal tax                  // <1>
+    BigDecimal total                // <1>
+
+    static mapping = {
+        tax   formula: 'subtotal * tax_rate'            // <2>
+        total formula: 'subtotal + (subtotal * tax_rate)'
+    }
+}
+----
+<1> `tax` and `total` have no corresponding columns in the table.
+<2> The formula is a raw SQL expression evaluated by the database.
+
+=== Reading Derived Values
+
+Derived properties are populated when an entity is loaded:
+
+[source,groovy]
+----
+def order = Order.get(1)
+println order.tax   // value computed by the database formula
+----
+
+WARNING: Derived properties are read-only. Setting them in Groovy code does 
not affect the database value — the formula always takes precedence when 
reloading.
+
+=== Column-Level Formulas (Read/Write Expressions)
+
+For finer control over individual column values, use `read` and `write` 
expressions on a regular property:
+
+[source,groovy]
+----
+class CreditCard {
+    String cardNumber
+    static mapping = {
+        cardNumber {
+            read  "decrypt(card_number)"    // <1>
+            write "encrypt(?)"              // <2>
+        }
+    }
+}
+----
+<1> SQL expression used when reading the column value.
+<2> SQL expression wrapping the bound parameter when writing.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/fetchingDSL.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/fetchingDSL.adoc
index e69de29bb2..aafa4b9662 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/fetchingDSL.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/fetchingDSL.adoc
@@ -0,0 +1,74 @@
+[[ormdsl-fetchingDSL]]
+== Fetching Strategies
+
+GORM supports both lazy (default) and eager fetching for associations. You can 
control this per-property via the ORM DSL `mapping` block.
+
+=== Lazy Fetching (Default)
+
+By default, associations are loaded lazily — Hibernate issues a secondary 
query only when you first access the association:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    // books are loaded lazily by default
+}
+----
+
+=== Eager Fetching
+
+To eagerly load an association in the same query as the owning entity, use 
`fetch: 'join'`:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    static mapping = {
+        books fetch: 'join'     // <1>
+    }
+}
+----
+<1> Hibernate uses a SQL `JOIN` to load `books` alongside the `Author`.
+
+You can also use `fetch: 'select'` to trigger a secondary `SELECT` eagerly (as 
opposed to lazy, which defers the select until access):
+
+[source,groovy]
+----
+static mapping = {
+    books fetch: 'select'   // loads eagerly via a secondary SELECT
+}
+----
+
+=== Batch Fetching
+
+Batch fetching is a performance optimisation that allows Hibernate to 
initialise multiple lazy proxies or collections in a single `SELECT`. Configure 
it with `batchSize`:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+    static mapping = {
+        books batchSize: 10     // <1>
+    }
+}
+----
+<1> When accessing `books` on an uninitialized proxy, Hibernate will fetch up 
to 10 collections in one query.
+
+Batch size can also be set at the class level, which affects all lazy-loaded 
instances of that class:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        batchSize 10
+    }
+}
+----
+
+=== Lazy vs. Eager — Recommendations
+
+TIP: Eager fetching avoids N+1 query problems but can return large result 
sets. Prefer lazy loading with explicit eager overrides (via named queries or 
`where` clauses with `.join()`) for fine-grained control.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/identity.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/identity.adoc
index e69de29bb2..3c53237d67 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/identity.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/identity.adoc
@@ -0,0 +1,65 @@
+[[ormdsl-identity]]
+== Identity
+
+GORM automatically adds an `id` property and a `version` property to every 
domain class. The `mapping` block lets you customise both.
+
+=== Generator Strategy
+
+The default generator is `native`, which delegates to the database for id 
generation (auto-increment, sequences, etc.). You can change this globally or 
per-class:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        id generator: 'sequence', params: [sequence_name: 'book_seq']   // <1>
+    }
+}
+----
+<1> Uses a named database sequence for the `id` column.
+
+Common generator values:
+
+[format="csv", options="header"]
+|===
+value,description
+`native`,Delegates to the database (auto-increment / sequence) — default
+`assigned`,Application assigns the id before saving
+`uuid`,Generates a UUID string id
+`sequence`,Uses a named database sequence (configure via `params`)
+`increment`,GORM-managed incrementing long — not suitable for clusters
+`identity`,Database `IDENTITY` / auto-increment column
+|===
+
+=== Column Name
+
+[source,groovy]
+----
+static mapping = {
+    id column: 'book_id'
+}
+----
+
+=== Composite Identifiers
+
+See xref:ormdsl-compositePrimaryKeys[Composite Primary Keys].
+
+=== Disabling Auto-generated Version
+
+The `version` column enables optimistic locking. To disable it:
+
+[source,groovy]
+----
+static mapping = {
+    version false
+}
+----
+
+You can also map it to a different column:
+
+[source,groovy]
+----
+static mapping = {
+    version column: 'revision'
+}
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/inheritanceStrategies.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/inheritanceStrategies.adoc
index e69de29bb2..9cb7d3ec84 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/inheritanceStrategies.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/inheritanceStrategies.adoc
@@ -0,0 +1,95 @@
+[[ormdsl-inheritanceStrategies]]
+== Inheritance Strategies
+
+GORM supports three Hibernate inheritance mapping strategies.
+
+=== Table-per-Hierarchy (Default)
+
+All classes in the hierarchy are stored in a single table. A discriminator 
column distinguishes rows for each subclass. This is the default:
+
+[source,groovy]
+----
+class Content {
+    String title
+    // tablePerHierarchy is true by default
+}
+
+class BlogPost extends Content {
+    String body
+}
+
+class Page extends Content {
+    String html
+}
+----
+
+The single table will contain columns for all properties of all subclasses, 
with nullable columns for subclass-specific fields.
+
+==== Customising the Discriminator
+
+[source,groovy]
+----
+class Content {
+    String title
+    static mapping = {
+        discriminator column: 'content_type', value: 'content'
+    }
+}
+
+class BlogPost extends Content {
+    static mapping = {
+        discriminator 'blog'    // <1>
+    }
+}
+----
+<1> The discriminator value stored for `BlogPost` rows.
+
+You can also configure the discriminator column type and whether it is 
insertable:
+
+[source,groovy]
+----
+static mapping = {
+    discriminator {
+        column name: 'dtype', sqlType: 'varchar(30)'
+        value  'blog'
+        insert false
+    }
+}
+----
+
+=== Table-per-Subclass
+
+Each subclass has its own table containing only the subclass-specific columns, 
joined to the parent table via a foreign key:
+
+[source,groovy]
+----
+class Content {
+    String title
+    static mapping = {
+        tablePerHierarchy false     // <1>
+    }
+}
+
+class BlogPost extends Content {
+    String body
+    // implicitly uses joined-subclass mapping
+}
+----
+<1> Disables single-table strategy; Hibernate will use joined subclass tables.
+
+=== Table-per-Concrete-Class
+
+Each concrete class has its own standalone table with all columns (inherited + 
its own). There is no shared parent table:
+
+[source,groovy]
+----
+class Content {
+    String title
+    static mapping = {
+        tablePerConcreteClass true  // <1>
+    }
+}
+----
+<1> Each concrete subclass gets its own fully self-contained table.
+
+TIP: Table-per-hierarchy is the most performant strategy because it requires 
no joins. Table-per-subclass is useful when you need to query on a subclass 
without nulls in the parent table. Table-per-concrete-class is least commonly 
used and makes polymorphic queries expensive.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/optimisticLockingAndVersioning.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/optimisticLockingAndVersioning.adoc
index e69de29bb2..a6b238d06a 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/optimisticLockingAndVersioning.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/optimisticLockingAndVersioning.adoc
@@ -0,0 +1,65 @@
+[[ormdsl-optimisticLockingAndVersioning]]
+== Optimistic Locking and Versioning
+
+GORM enables optimistic locking by default via a `version` column added to 
every domain class table.
+
+=== How Optimistic Locking Works
+
+When you call `save()`, Hibernate checks that the `version` in the database 
matches the version loaded by the current session. If another transaction 
modified the row in between, the versions will differ and Hibernate throws 
`StaleObjectStateException`:
+
+[source,groovy]
+----
+def book = Book.get(1)
+// ... another thread or transaction updates the same book row ...
+book.title = "New Title"
+book.save()  // throws StaleObjectStateException if version was incremented 
elsewhere
+----
+
+Handle this with a try/catch in your service or controller:
+
+[source,groovy]
+----
+try {
+    book.save(failOnError: true)
+} catch (org.hibernate.StaleObjectStateException e) {
+    // handle conflict: reload and retry, or inform the user
+}
+----
+
+=== Disabling Optimistic Locking
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        version false   // <1>
+    }
+}
+----
+<1> No `version` column is created; concurrent modifications are not detected.
+
+WARNING: Disabling versioning removes all optimistic locking protection. 
Concurrent updates to the same row will silently overwrite each other.
+
+=== Customising the Version Column
+
+[source,groovy]
+----
+static mapping = {
+    version column: 'revision'
+}
+----
+
+=== Locking Pessimistically
+
+For cases where you need a database-level lock, use GORM's `lock()` method:
+
+[source,groovy]
+----
+Book.withTransaction {
+    def book = Book.lock(1)   // <1>
+    book.title = "Locked Update"
+    book.save()
+}
+----
+<1> Issues a `SELECT ... FOR UPDATE`, preventing other transactions from 
reading or modifying the row until the transaction commits.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/tableAndColumnNames.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/tableAndColumnNames.adoc
index e69de29bb2..cecff6cd41 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/tableAndColumnNames.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/advancedGORMFeatures/ormdsl/tableAndColumnNames.adoc
@@ -0,0 +1,123 @@
+[[ormdsl-tableAndColumnNames]]
+== Table and Column Names
+
+By default GORM derives table and column names from your domain class and 
property names using an underscore-based naming strategy. You can override 
these defaults with the ORM DSL `mapping` block.
+
+=== Changing the Table Name
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        table 'books'           // <1>
+    }
+}
+----
+<1> Maps the `Book` domain class to a table named `books`.
+
+You can also specify a catalog and/or schema:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        table name: 'books', catalog: 'inventory', schema: 'dbo'
+    }
+}
+----
+
+=== Changing Column Names
+
+Use the property name followed by `column` to override the column name for any 
property:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static mapping = {
+        title column: 'book_title'
+    }
+}
+----
+
+For multi-column user types, call `column` multiple times:
+
+[source,groovy]
+----
+class Payment {
+    Money amount
+    static mapping = {
+        amount {
+            column name: 'amount_value'
+            column name: 'amount_currency'
+        }
+    }
+}
+----
+
+=== Column Properties
+
+The `column` block supports the following attributes:
+
+[format="csv", options="header"]
+|===
+attribute,description,default
+`name`,The column name,derived from property name
+`sqlType`,The SQL type override,derived from Hibernate type
+`unique`,Whether the column has a unique constraint,`false`
+`index`,Index name (or `true` for an auto-named index),none
+`defaultValue`,The DDL default value for the column,none
+`comment`,A DDL comment for the column,none
+`read`,A SQL expression to use when reading the value,none
+`write`,A SQL expression to use when writing the value,none
+|===
+
+=== Join Table Configuration for Collections
+
+When a domain class has a `hasMany` relationship without a `belongsTo` on the 
other side (unidirectional), or for `hasMany` of basic/enum types, GORM uses a 
join table. You can customise the join table name and its columns:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books joinTable: 'author_books'     // <1>
+    }
+}
+----
+<1> Override the join table name only.
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books joinTable: [
+            name: 'author_books',       // <1>
+            key: 'author_fk',           // <2>
+            column: 'book_fk'           // <3>
+        ]
+    }
+}
+----
+<1> The join table name.
+<2> The foreign-key column that points back to `Author`.
+<3> The foreign-key column that points to `Book` (or holds the element value 
for basic types).
+
+You can also use the closure form:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books joinTable {
+            name 'author_books'
+            key  'author_fk'
+            column 'book_fk'
+        }
+    }
+}
+----
diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses.adoc
index e69de29bb2..6d2b13ab03 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses.adoc
@@ -0,0 +1,66 @@
+[[domainClasses]]
+== Domain Classes
+
+Domain classes are the heart of a GORM application. They represent the data 
model and are mapped to database tables automatically by convention.
+
+=== Anatomy of a Domain Class
+
+[source,groovy]
+----
+class Book {
+    String title
+    String author
+    Integer pages
+    Date dateCreated         // <1>
+    Date lastUpdated         // <1>
+
+    static constraints = {   // <2>
+        title  blank: false, maxSize: 255
+        author blank: false
+        pages  min: 1, nullable: true
+    }
+
+    static mapping = {       // <3>
+        table 'books'
+        title index: true
+    }
+}
+----
+<1> `dateCreated` and `lastUpdated` are automatically timestamped by GORM.
+<2> The `constraints` block defines validation rules and column constraints.
+<3> The `mapping` block customises the Hibernate ORM mapping.
+
+=== Automatic Properties
+
+Every domain class automatically gets:
+
+[cols="1,2"]
+|===
+|Property | Description
+
+|`id`
+|Auto-generated primary key (`Long` by default)
+
+|`version`
+|Optimistic locking version column (`Long`)
+|===
+
+And auto-timestamped properties if declared:
+
+[cols="1,2"]
+|===
+|Property | Description
+
+|`dateCreated`
+|Set to the current timestamp on first save
+
+|`lastUpdated`
+|Updated to the current timestamp on every save
+|===
+
+Refer to the following sections for details on domain class features:
+
+* xref:domainClasses-setsListsAndMaps[Sets, Lists and Maps]
+* xref:domainClasses-gormAssociation[GORM Associations]
+* xref:domainClasses-gormComposition[GORM Composition]
+* xref:domainClasses-inheritanceInGORM[Inheritance in GORM]
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation.adoc
index e69de29bb2..7b54fcda8b 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation.adoc
@@ -0,0 +1,28 @@
+[[domainClasses-gormAssociation]]
+== GORM Associations
+
+GORM supports all standard relationship types between domain classes. Each 
association type maps to a specific Hibernate/database pattern.
+
+[cols="1,2"]
+|===
+|Association type | Declared with
+
+|Many-to-one / One-to-one
+|A property of the target type
+
+|One-to-many (bidirectional)
+|`hasMany` + `belongsTo`
+
+|One-to-many (unidirectional)
+|`hasMany` only (join table)
+
+|Many-to-many
+|`hasMany` on both sides + `belongsTo` on one
+|===
+
+Refer to the following subsections for details on each association type:
+
+* xref:gormAssociation-manyToOneAndOneToOne[Many-to-One and One-to-One]
+* xref:gormAssociation-oneToMany[One-to-Many]
+* xref:gormAssociation-manyToMany[Many-to-Many]
+* xref:gormAssociation-basicCollectionTypes[Basic Collection Types]
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/basicCollectionTypes.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/basicCollectionTypes.adoc
index e69de29bb2..862489a65e 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/basicCollectionTypes.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/basicCollectionTypes.adoc
@@ -0,0 +1,88 @@
+[[gormAssociation-basicCollectionTypes]]
+== Basic Collection Types
+
+In addition to collections of domain objects, GORM supports collections of 
basic types — strings, numbers, enums, and other persistable values. These are 
stored in a separate join table.
+
+=== String Collections
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [nicknames: String]    // <1>
+}
+----
+<1> A join table `author_nicknames` is created with a `nicknames` column 
holding the string values.
+
+=== Numeric Collections
+
+[source,groovy]
+----
+class Survey {
+    String question
+    static hasMany = [scores: Integer]
+}
+----
+
+=== Enum Collections
+
+Collections of `enum` types are supported:
+
+[source,groovy]
+----
+enum Status { ACTIVE, INACTIVE, SUSPENDED }
+
+class Account {
+    String name
+    static hasMany = [allowedStatuses: Status]  // <1>
+}
+----
+<1> A join table `account_allowed_statuses` is created. Enum values are stored 
using their ordinal position by default.
+
+To store enum values as their string names instead of ordinals, configure the 
`enumType` on the column:
+
+[source,groovy]
+----
+class Account {
+    static hasMany = [allowedStatuses: Status]
+    static mapping = {
+        allowedStatuses {
+            column enumType: 'string'   // <1>
+        }
+    }
+}
+----
+<1> Stores `'ACTIVE'`, `'INACTIVE'`, etc. instead of `0`, `1`, `2`.
+
+=== Customising the Join Table
+
+You can override the join table name and the value column name:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [nicknames: String]
+    static mapping = {
+        nicknames joinTable: [
+            name:   'author_alias',     // <1>
+            column: 'alias_value'       // <2>
+        ]
+    }
+}
+----
+<1> The join table name.
+<2> The column that holds the basic value.
+
+=== Accessing and Modifying
+
+Basic collections behave like any other GORM `hasMany` — use `addTo*` and 
`removeFrom*`:
+
+[source,groovy]
+----
+def author = Author.get(1)
+author.addToNicknames('Graeme')
+author.save()
+
+author.removeFromNicknames('Graeme')
+author.save()
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToMany.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToMany.adoc
index e69de29bb2..02518a8d5c 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToMany.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToMany.adoc
@@ -0,0 +1,68 @@
+[[gormAssociation-manyToMany]]
+== Many-to-Many Associations
+
+A many-to-many association is created when both domain classes declare 
`hasMany` pointing at each other, and one side also declares `belongsTo`.
+
+=== Declaring the Relationship
+
+[source,groovy]
+----
+class Book {
+    String title
+    static hasMany  = [authors: Author]
+    static belongsTo = Author               // <1>
+}
+
+class Author {
+    String name
+    static hasMany = [books: Book]
+}
+----
+<1> `belongsTo` without a property name makes `Book` the owned side. The 
owning side (`Author`) controls cascade save/delete.
+
+GORM creates a join table `author_books` with foreign-key columns for both 
sides.
+
+=== Saving a Many-to-Many
+
+Always save from the owning side (the side that does **not** have `belongsTo`):
+
+[source,groovy]
+----
+def author = new Author(name: 'Graeme Rocher')
+def book   = new Book(title:  'Grails in Action')
+
+author.addToBooks(book)
+author.save()           // <1>
+----
+<1> `book` is cascade-saved because `Author` is the owning side.
+
+=== Join Table Customisation
+
+Override the join table name and columns in the `mapping` block:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books joinTable: [
+            name:   'author_to_book',
+            key:    'auth_id',
+            column: 'book_id'
+        ]
+    }
+}
+----
+
+=== Bidirectional Access
+
+Both sides of the relationship can be navigated:
+
+[source,groovy]
+----
+Author author = Author.get(1)
+author.books.each { println it.title }
+
+Book book = Book.get(1)
+book.authors.each { println it.name }
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToOneAndOneToOne.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToOneAndOneToOne.adoc
index e69de29bb2..cc459d4c35 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToOneAndOneToOne.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/manyToOneAndOneToOne.adoc
@@ -0,0 +1,78 @@
+[[gormAssociation-manyToOneAndOneToOne]]
+== Many-to-One and One-to-One Associations
+
+=== Many-to-One
+
+Declare a many-to-one association by adding a property of the target domain 
class type:
+
+[source,groovy]
+----
+class Book {
+    String title
+    Author author           // <1>
+}
+
+class Author {
+    String name
+}
+----
+<1> A foreign key column `author_id` is added to the `book` table.
+
+When combined with `belongsTo`, the association participates in cascade 
save/delete:
+
+[source,groovy]
+----
+class Book {
+    String title
+    static belongsTo = [author: Author]     // <1>
+}
+----
+<1> The `author` property is added implicitly; deleting `Author` cascades to 
`Book`.
+
+=== One-to-One
+
+A one-to-one association is also declared as a simple property, but each 
`Author` can only have one `Biography`:
+
+[source,groovy]
+----
+class Author {
+    String name
+    Biography biography      // <1>
+}
+
+class Biography {
+    String summary
+    static belongsTo = [author: Author]
+}
+----
+<1> A unique foreign key `biography_id` is added to `author`.
+
+=== Configuring the Foreign Key Column
+
+Override the foreign key column name in the `mapping` block:
+
+[source,groovy]
+----
+class Book {
+    String title
+    Author author
+    static mapping = {
+        author column: 'fk_author'
+    }
+}
+----
+
+=== Nullable Associations
+
+By default, GORM-managed foreign key columns are non-nullable. To allow null:
+
+[source,groovy]
+----
+class Book {
+    Author author
+
+    static constraints = {
+        author nullable: true
+    }
+}
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/oneToMany.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/oneToMany.adoc
index e69de29bb2..ed9266f17e 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/oneToMany.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormAssociation/oneToMany.adoc
@@ -0,0 +1,71 @@
+[[gormAssociation-oneToMany]]
+== One-to-Many Associations
+
+A one-to-many association is declared using `hasMany`. It represents a 
collection of associated domain objects.
+
+=== Bidirectional One-to-Many
+
+When both sides declare the relationship, GORM manages the foreign key on the 
many side's table:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]  // <1>
+}
+
+class Book {
+    String title
+    Author author                   // <2>
+    static belongsTo = [author: Author]
+}
+----
+<1> `Author` owns a collection of `Book` objects.
+<2> `Book` declares the back-reference. `belongsTo` also enables cascade 
delete.
+
+With `belongsTo`, deleting an `Author` will cascade-delete all of its `books`.
+
+=== Unidirectional One-to-Many
+
+Without `belongsTo` on the other side, GORM uses a join table to maintain the 
relationship:
+
+[source,groovy]
+----
+class Author {
+    String name
+    static hasMany = [books: Book]
+}
+
+class Book {
+    String title
+    // no belongsTo or author property
+}
+----
+
+The join table name defaults to `author_books` and can be customised — see 
xref:ormdsl-tableAndColumnNames[Table and Column Names].
+
+=== Sorting
+
+You can define a default sort order for the collection:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books sort: 'title', order: 'asc'
+    }
+}
+----
+
+=== Adding and Removing Items
+
+[source,groovy]
+----
+def author = Author.get(1)
+author.addToBooks(new Book(title: 'Groovy in Action'))
+author.save()
+
+author.removeFromBooks(author.books.first())
+author.save()
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormComposition.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormComposition.adoc
index e69de29bb2..2e77b9cd76 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormComposition.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/gormComposition.adoc
@@ -0,0 +1,61 @@
+[[domainClasses-gormComposition]]
+== GORM Composition (Embedded Objects)
+
+GORM supports composition via `embedded`, which maps a non-domain class as a 
set of columns on the owning table rather than a separate table.
+
+=== Declaring an Embedded Component
+
+[source,groovy]
+----
+class Address {
+    String street
+    String city
+    String postalCode
+    String country
+}
+
+class Person {
+    String name
+    Address address             // <1>
+
+    static embedded = ['address']   // <2>
+}
+----
+<1> `Address` is a plain Groovy class (not a domain class).
+<2> Declaring it in `embedded` maps its properties as columns on the `person` 
table.
+
+The `person` table will contain columns: `name`, `address_street`, 
`address_city`, `address_postal_code`, `address_country`.
+
+=== Overriding Column Names
+
+Use the `mapping` block to rename the embedded columns:
+
+[source,groovy]
+----
+class Person {
+    static embedded = ['address']
+    static mapping = {
+        address {
+            street  column: 'addr_street'
+            city    column: 'addr_city'
+        }
+    }
+}
+----
+
+=== Nullable Embedded Objects
+
+If the embedded object can be absent, mark it as nullable in constraints:
+
+[source,groovy]
+----
+class Person {
+    Address address
+    static embedded  = ['address']
+    static constraints = {
+        address nullable: true
+    }
+}
+----
+
+NOTE: Embedded components are always persisted as part of the owning entity. 
There is no separate table, no `id`, and no lifecycle management for the 
embedded object.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/inheritanceInGORM.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/inheritanceInGORM.adoc
index e69de29bb2..66a7d3bf83 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/inheritanceInGORM.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/inheritanceInGORM.adoc
@@ -0,0 +1,54 @@
+[[domainClasses-inheritanceInGORM]]
+== Inheritance in GORM
+
+GORM supports standard Groovy/Java class inheritance. Domain classes in a 
hierarchy all benefit from GORM persistence.
+
+See xref:ormdsl-inheritanceStrategies[Inheritance Strategies] for the 
available mapping strategies (table-per-hierarchy, table-per-subclass, 
table-per-concrete-class) and how to configure them.
+
+=== Basic Inheritance
+
+[source,groovy]
+----
+class Content {
+    String title
+    Date dateCreated
+}
+
+class BlogPost extends Content {
+    String body
+    String author
+}
+
+class Page extends Content {
+    String html
+    String slug
+}
+----
+
+By default all three classes are stored in a single `content` table 
(table-per-hierarchy). GORM uses a `class` discriminator column to distinguish 
rows.
+
+=== Querying the Hierarchy
+
+GORM queries are polymorphic by default — querying the parent class returns 
instances of all subclasses:
+
+[source,groovy]
+----
+List<Content> all = Content.list()      // returns BlogPost and Page instances
+
+List<BlogPost> posts = BlogPost.list()  // returns only BlogPost instances
+----
+
+=== Abstract Base Classes
+
+You can use abstract domain classes as the root of a hierarchy. Abstract 
classes have no corresponding rows and cannot be instantiated directly:
+
+[source,groovy]
+----
+abstract class Content {
+    String title
+}
+
+class BlogPost extends Content { ... }
+----
+
+TIP: Prefer table-per-hierarchy (the default) for most use cases. It requires 
no `JOIN` for polymorphic queries and is the most performant strategy.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/sets,ListsAndMaps.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/sets,ListsAndMaps.adoc
index e69de29bb2..c9183bd601 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/sets,ListsAndMaps.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/domainClasses/sets,ListsAndMaps.adoc
@@ -0,0 +1,69 @@
+[[domainClasses-setsListsAndMaps]]
+== Sets, Lists and Maps
+
+By default `hasMany` creates a `java.util.Set` collection (unordered, no 
duplicates). GORM also supports `List` and `Map` collection types.
+
+=== Sets (Default)
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]  // Set<Book> by default
+}
+----
+
+=== Lists (Ordered)
+
+Declare the collection property as a `List` to use a positional, ordered 
collection. GORM adds an `index` column to the join table:
+
+[source,groovy]
+----
+class Author {
+    List books                      // <1>
+    static hasMany = [books: Book]
+}
+----
+<1> Declaring the field type as `List` tells GORM to use a list mapping with a 
position index.
+
+[source,groovy]
+----
+def author = Author.get(1)
+author.books[0]     // <1>
+----
+<1> Access by position — Hibernate maintains the order using an `idx` column 
in the join table.
+
+=== Maps (Key-Value)
+
+Declare the collection property as a `Map` to store key-value pairs. The key 
is typically a `String`:
+
+[source,groovy]
+----
+class Author {
+    Map books                       // <1>
+    static hasMany = [books: Book]
+}
+----
+<1> Keys and values are stored in the join table.
+
+[source,groovy]
+----
+def author = Author.get(1)
+author.books['grailsInAction']      // <1>
+----
+<1> Access by key.
+
+=== Sorting Sets
+
+For `Set`-based collections, define a default sort order in the `mapping` 
block:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books sort: 'title', order: 'asc'
+    }
+}
+----
+
+TIP: `List` mappings incur the cost of maintaining a positional index column 
on every insert/reorder. Use them only when ordering matters. For most 
associations, the default `Set` is the better choice.
diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction.adoc
index e69de29bb2..ae4b738219 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/introduction.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/introduction.adoc
@@ -0,0 +1,53 @@
+[[introduction]]
+== Introduction
+
+GORM for Hibernate 7 (grails-data-hibernate7) is the Hibernate 7 persistence 
layer for GORM, the GRAILS Object Relational Mapping framework. It provides a 
high-level, convention-over-configuration API for mapping Groovy domain classes 
to a relational database via Hibernate ORM 7 and Jakarta EE 10.
+
+=== Features
+
+* Convention-based ORM mapping — minimal configuration for common patterns
+* Full Hibernate 7 support with Jakarta EE 10 (`jakarta.*` packages)
+* Spring Boot 3.5 integration
+* Dynamic finders, named queries, `where` query DSL, HQL, and native SQL
+* Optimistic locking, second-level caching, and batch fetching
+* Comprehensive association mapping: one-to-one, one-to-many, many-to-many, 
basic collections
+* Multiple inheritance strategies: table-per-hierarchy, table-per-subclass, 
table-per-concrete-class
+* Multi-tenancy support
+* Groovy `static mapping {}` DSL for full control over table/column names, 
types, and strategies
+
+=== Requirements
+
+[format="csv", options="header"]
+|===
+Component,Version
+JDK,17+
+Groovy,4.0.x
+Spring Boot,3.5.x
+Hibernate ORM,7.x
+Jakarta EE,10
+|===
+
+=== Quick Start
+
+Add the dependency to your Grails application and define a domain class:
+
+[source,groovy]
+----
+class Book {
+    String title
+    String author
+    Date dateCreated
+    Date lastUpdated
+
+    static constraints = {
+        title blank: false
+        author blank: false
+    }
+}
+----
+
+GORM automatically:
+
+* Creates a `book` table with `id`, `version`, `title`, `author`, 
`date_created`, and `last_updated` columns
+* Adds dynamic finders like `Book.findByTitle('...')`, 
`Book.findAllByAuthor('...')`
+* Injects `save()`, `delete()`, `get()`, `list()`, and other persistence 
methods
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics.adoc
index e69de29bb2..60841544e4 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics.adoc
@@ -0,0 +1,4 @@
+[[persistenceBasics]]
+== Persistence Basics
+
+This section covers the core persistence operations available on every GORM 
domain class: saving, updating, deleting, querying for changes, and transaction 
management.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/cascades.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/cascades.adoc
index e69de29bb2..afae3b3bef 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/cascades.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/cascades.adoc
@@ -0,0 +1,44 @@
+[[persistenceBasics-cascades]]
+== Cascades
+
+Hibernate cascades propagate persistence operations from a parent entity to 
its associated children automatically.
+
+See xref:ormdsl-customCascadeBehaviour[Custom Cascade Behaviour] for the full 
reference on configuring cascade behaviour via the `mapping` block.
+
+=== Default Cascade Behaviour
+
+GORM applies `save-update` cascading by default on associations managed by 
`hasMany`. This means:
+
+- Saving an `Author` also saves any new or modified `Book` objects in its 
`books` collection.
+- **Deleting an `Author` does NOT automatically delete its `books`** unless 
`belongsTo` is declared or `cascade: 'all'` is configured.
+
+=== Cascade with `belongsTo`
+
+Declaring `belongsTo` on the owned side automatically adds cascade-delete from 
the owning side:
+
+[source,groovy]
+----
+class Book {
+    static belongsTo = [author: Author]     // <1>
+}
+----
+<1> Deleting an `Author` cascade-deletes all associated `Book` rows.
+
+=== Cascade with `all-delete-orphan`
+
+Use `all-delete-orphan` to delete child rows that are removed from the 
collection:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+    static mapping = {
+        books cascade: 'all-delete-orphan'
+    }
+}
+
+def author = Author.get(1)
+author.books.remove(author.books.first())   // <1>
+author.save()
+----
+<1> The removed `Book` will be deleted from the database.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/deletingObjects.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/deletingObjects.adoc
index e69de29bb2..51bc5d887c 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/deletingObjects.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/deletingObjects.adoc
@@ -0,0 +1,53 @@
+[[persistenceBasics-deletingObjects]]
+== Deleting Objects
+
+Call `delete()` on a loaded instance to remove it from the database:
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.delete()
+----
+
+=== Flush on Delete
+
+[source,groovy]
+----
+book.delete(flush: true)    // issues DELETE immediately
+----
+
+=== Cascade Delete
+
+When a domain class declares `belongsTo`, deleting the parent also deletes its 
children:
+
+[source,groovy]
+----
+class Author {
+    static hasMany = [books: Book]
+}
+
+class Book {
+    static belongsTo = [author: Author]
+}
+
+// Deletes the author AND all associated books
+Author.get(1).delete()
+----
+
+To delete without cascading, remove the `belongsTo` and configure cascade 
behaviour explicitly — see xref:ormdsl-customCascadeBehaviour[Custom Cascade 
Behaviour].
+
+=== Bulk Delete
+
+Use `deleteAll()` to delete all instances matching a criteria:
+
+[source,groovy]
+----
+Book.where { genre == 'Horror' }.deleteAll()
+----
+
+Or with HQL:
+
+[source,groovy]
+----
+Book.executeUpdate("delete Book where genre = :genre", [genre: 'Horror'])
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/fetching.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/fetching.adoc
index e69de29bb2..eba41bb1ca 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/fetching.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/fetching.adoc
@@ -0,0 +1,55 @@
+[[persistenceBasics-fetching]]
+== Fetching
+
+Controlling how and when associated data is loaded is critical for application 
performance.
+
+See xref:ormdsl-fetchingDSL[Fetching Strategies] for full configuration 
details.
+
+=== Default: Lazy Loading
+
+Associations are loaded lazily by default — Hibernate does not query 
associated data until you access it:
+
+[source,groovy]
+----
+def author = Author.get(1)      // SELECT * FROM author WHERE id=1
+author.books.size()             // SELECT * FROM book WHERE author_id=1 
(triggered now)
+----
+
+=== N+1 Problem
+
+Loading a list of authors and accessing their books triggers one query per 
author:
+
+[source,groovy]
+----
+Author.list().each { author ->
+    println author.books.size()     // <1>
+}
+----
+<1> N additional queries for N authors — the N+1 problem.
+
+=== Solution: Eager Fetching with Join
+
+[source,groovy]
+----
+// Option 1: query-time join
+def authors = Author.findAll {
+    join 'books'
+}
+
+// Option 2: mapping-level eager fetch (always eager — use with care)
+static mapping = {
+    books fetch: 'join'
+}
+----
+
+=== Batch Fetching
+
+A lighter alternative to `join` — fetch collections in batches to reduce query 
count without a cartesian product:
+
+[source,groovy]
+----
+static mapping = {
+    books batchSize: 10     // <1>
+}
+----
+<1> Hibernate will initialise up to 10 book collections with a single `IN` 
query.
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/locking.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/locking.adoc
index e69de29bb2..9f152a8c45 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/locking.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/locking.adoc
@@ -0,0 +1,40 @@
+[[persistenceBasics-locking]]
+== Locking
+
+=== Optimistic Locking
+
+GORM enables optimistic locking by default via a `version` column. See 
xref:ormdsl-optimisticLockingAndVersioning[Optimistic Locking and Versioning] 
for full details.
+
+=== Pessimistic Locking
+
+To acquire a database-level lock on a row, use `lock()`:
+
+[source,groovy]
+----
+Book.withTransaction {
+    def book = Book.lock(1)         // <1>
+    book.title = 'Updated Safely'
+    book.save()
+}                                   // <2>
+----
+<1> Issues `SELECT ... FOR UPDATE`, preventing concurrent reads/writes to this 
row.
+<2> Lock is released when the transaction commits.
+
+You can also lock an already-loaded instance:
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.lock()                         // upgrades to a pessimistic lock
+----
+
+=== Refresh
+
+To reload the current state from the database (discarding in-memory changes):
+
+[source,groovy]
+----
+def book = Book.get(1)
+// ... another thread modifies the book ...
+book.refresh()                      // re-reads from the database
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/modificationChecking.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/modificationChecking.adoc
index e69de29bb2..8e4b97d243 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/modificationChecking.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/modificationChecking.adoc
@@ -0,0 +1,45 @@
+[[persistenceBasics-modificationChecking]]
+== Modification Checking
+
+Hibernate tracks which properties have been modified since the entity was 
loaded. GORM exposes this via `isDirty()` and related methods.
+
+=== Checking if an Instance is Dirty
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.isDirty()      // false — just loaded
+
+book.title = 'New Title'
+book.isDirty()      // true — title has changed
+----
+
+=== Checking a Specific Property
+
+[source,groovy]
+----
+book.isDirty('title')   // true
+book.isDirty('genre')   // false — genre unchanged
+----
+
+=== Getting the Original Value
+
+[source,groovy]
+----
+def book = Book.get(1)
+println book.title          // 'Original Title'
+book.title = 'New Title'
+println book.getPersistentValue('title')    // 'Original Title'
+----
+
+=== Dirty Properties
+
+Get a list of all property names that have changed:
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.title = 'New Title'
+book.genre = 'Fiction'
+println book.dirtyPropertyNames    // ['title', 'genre']
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/savingAndUpdating.adoc
 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/savingAndUpdating.adoc
index e69de29bb2..056658d272 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/savingAndUpdating.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/persistenceBasics/savingAndUpdating.adoc
@@ -0,0 +1,76 @@
+[[persistenceBasics-savingAndUpdating]]
+== Saving and Updating
+
+=== Saving
+
+Call `save()` on a domain instance to persist it. GORM delegates to 
Hibernate's `Session.saveOrUpdate()`:
+
+[source,groovy]
+----
+def book = new Book(title: 'Groovy in Action', author: 'Dierk König')
+book.save()
+----
+
+If validation fails, `save()` returns `null` and the errors are available on 
the instance:
+
+[source,groovy]
+----
+def book = new Book(title: '')   // violates blank constraint
+if (!book.save()) {
+    book.errors.allErrors.each { println it }
+}
+----
+
+=== Fail on Error
+
+Use `failOnError: true` to throw a `ValidationException` instead of returning 
`null`:
+
+[source,groovy]
+----
+book.save(failOnError: true)    // throws ValidationException on constraint 
violation
+----
+
+=== Flush
+
+By default Hibernate delays SQL writes until the session is flushed. Force an 
immediate flush:
+
+[source,groovy]
+----
+book.save(flush: true)      // <1>
+----
+<1> Issues the `INSERT` or `UPDATE` immediately.
+
+=== Updating
+
+Modify properties on a loaded instance and call `save()`:
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.title = 'Updated Title'
+book.save()
+----
+
+=== Dynamic Update
+
+To generate `UPDATE` statements that only include changed columns (useful for 
wide tables), enable `dynamicUpdate`:
+
+[source,groovy]
+----
+class Book {
+    static mapping = {
+        dynamicUpdate true
+    }
+}
+----
+
+=== Dynamic Insert
+
+Similarly, `dynamicInsert` generates `INSERT` statements that omit null 
properties:
+
+[source,groovy]
+----
+static mapping = {
+    dynamicInsert true
+}
+----
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/programmaticTransactions.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/programmaticTransactions.adoc
index e69de29bb2..32a60e62c6 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/programmaticTransactions.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/programmaticTransactions.adoc
@@ -0,0 +1,73 @@
+[[programmaticTransactions]]
+== Programmatic Transactions
+
+GORM integrates with Spring's transaction management. All persistence 
operations should run within a transaction.
+
+=== `withTransaction`
+
+Use `withTransaction` on any domain class to run a block within a transaction:
+
+[source,groovy]
+----
+Book.withTransaction {
+    new Book(title: 'Grails in Action', author: 'Glen Smith').save()
+    new Book(title: 'Groovy in Action', author: 'Dierk König').save()
+    // both are committed together; any exception rolls back both
+}
+----
+
+The closure receives a `TransactionStatus` parameter if needed:
+
+[source,groovy]
+----
+Book.withTransaction { TransactionStatus status ->
+    def book = new Book(title: 'Test')
+    book.save()
+    if (someCondition) {
+        status.setRollbackOnly()    // <1>
+    }
+}
+----
+<1> Marks the transaction for rollback without throwing an exception.
+
+=== `withNewTransaction`
+
+Start a new, independent transaction (suspending the current one if any):
+
+[source,groovy]
+----
+Book.withNewTransaction {
+    // runs in a brand-new transaction regardless of any outer transaction
+}
+----
+
+=== `withSession`
+
+Access the underlying Hibernate `Session` directly:
+
+[source,groovy]
+----
+Book.withSession { session ->
+    session.flush()
+    session.clear()     // <1>
+}
+----
+<1> Evicts all entities from the first-level cache.
+
+=== Service-Layer Transactions
+
+In a Grails application, services are transactional by default. Annotate 
individual methods or the entire service class with Spring's `@Transactional` 
for fine-grained control:
+
+[source,groovy]
+----
+import org.springframework.transaction.annotation.Transactional
+
+@Transactional
+class BookService {
+    def transferOwnership(Long bookId, Long newAuthorId) {
+        def book = Book.get(bookId)
+        book.author = Author.get(newAuthorId)
+        book.save(failOnError: true)
+    }
+}
+----
diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/querying.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/querying.adoc
index e69de29bb2..8e9c9f846d 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/querying.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/querying.adoc
@@ -0,0 +1,39 @@
+[[querying]]
+== Querying
+
+GORM provides multiple querying mechanisms, ranging from simple dynamic 
finders to full SQL queries.
+
+* xref:querying-whereQueries[Where Queries (Criteria DSL)] — type-safe Groovy 
criteria queries
+* xref:querying-hql[HQL Queries] — Hibernate Query Language
+* xref:querying-nativeSql[Native SQL Queries] — raw database SQL via Hibernate
+
+=== Dynamic Finders
+
+The simplest form of querying uses auto-generated finder methods based on 
property names:
+
+[source,groovy]
+----
+Book.findByTitle('Groovy in Action')
+Book.findAllByAuthorAndGenre('Dierk König', 'Tech')
+Book.countByGenre('Fiction')
+Book.findByTitleLike('%Groovy%')
+Book.findAllByPagesGreaterThan(300)
+Book.findAllByTitleIlike('%groovy%')    // case-insensitive
+----
+
+Finder methods support pagination:
+
+[source,groovy]
+----
+Book.findAllByGenre('Fiction', [max: 10, offset: 0, sort: 'title', order: 
'asc'])
+----
+
+=== `get`, `list`, `count`
+
+[source,groovy]
+----
+Book.get(1)                                 // by id
+Book.list()                                 // all
+Book.list(max: 10, offset: 20)             // paginated
+Book.count()                                // total count
+----
diff --git a/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide.adoc
index e69de29bb2..8c9250307e 100644
--- a/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide.adoc
+++ b/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide.adoc
@@ -0,0 +1,7 @@
+[[quickStartGuide]]
+== Quick Start Guide
+
+This section covers getting up and running with GORM for Hibernate 7 quickly.
+
+For full configuration options, see xref:configuration[Configuration].
+For persistence basics, see xref:persistenceBasics[Persistence Basics].
diff --git 
a/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide/basicCRUD.adoc 
b/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide/basicCRUD.adoc
index e69de29bb2..d235c1bc18 100644
--- 
a/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide/basicCRUD.adoc
+++ 
b/grails-data-hibernate7/docs/src/docs/asciidoc/quickStartGuide/basicCRUD.adoc
@@ -0,0 +1,89 @@
+[[quickStartGuide-basicCRUD]]
+== Basic CRUD
+
+Every GORM domain class automatically gets Create, Read, Update, and Delete 
(CRUD) operations.
+
+=== Create
+
+[source,groovy]
+----
+// Constructor with named parameters
+def book = new Book(title: 'Groovy in Action', author: 'Dierk König')
+book.save()
+
+// Or using the create() factory method
+def book = Book.create(title: 'Grails in Action', author: 'Glen Smith')
+----
+
+=== Read
+
+[source,groovy]
+----
+// By primary key
+def book = Book.get(1)
+
+// Returns null if not found
+def book = Book.get(999)    // null
+
+// Get multiple by IDs
+def books = Book.getAll(1, 2, 3)
+
+// Load a proxy (no immediate SELECT)
+def book = Book.load(1)
+
+// List all
+def books = Book.list()
+
+// With pagination
+def books = Book.list(max: 10, offset: 0, sort: 'title', order: 'asc')
+
+// Dynamic finders
+def book  = Book.findByTitle('Groovy in Action')
+def books = Book.findAllByAuthor('Dierk König')
+def count = Book.countByAuthor('Dierk König')
+----
+
+=== Update
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.title = 'Updated Title'
+book.save()
+----
+
+=== Delete
+
+[source,groovy]
+----
+def book = Book.get(1)
+book.delete()
+----
+
+=== Validation
+
+`save()` runs constraints before persisting and returns `null` if validation 
fails:
+
+[source,groovy]
+----
+def book = new Book(title: '')          // blank title violates constraint
+if (!book.save()) {
+    println book.errors.allErrors       // print validation errors
+}
+
+// Throw on failure instead
+book.save(failOnError: true)            // throws ValidationException
+----
+
+=== Transactions
+
+GORM operations run inside Hibernate sessions. Use `withTransaction` for 
explicit transaction control:
+
+[source,groovy]
+----
+Book.withTransaction {
+    def book = new Book(title: 'Tx Book', author: 'Author')
+    book.save()
+    // any exception here rolls back the transaction
+}
+----

Reply via email to