GORM Relationships

Harry · 13 Sep 2026 · 2 views

Why Relationships Matter

Real data is connected: users have roles, orders have items, employees belong to departments, customers place orders. GORM models these relationships naturally and handles foreign keys, join tables, cascades, and fetch strategies for you.

One-to-One

class User {
    String username
    static hasOne = [profile: Profile]
}

class Profile {
    String fullName
    String phone
    static belongsTo = [user: User]
}

hasOne defines ownership; belongsTo enables cascading deletes.

One-to-Many

class Author {
    String name
    static hasMany = [books: Book]
}

class Book {
    String title
    static belongsTo = [author: Author]
}

Grails adds the foreign key to the book table and handles cascades. Adding data uses addToBooks:

def author = new Author(name: "John")
author.addToBooks(new Book(title: "Grails Basics"))
author.save()

Many-to-Many

class User {
    String username
    static hasMany = [roles: Role]
}

class Role {
    String authority
    static hasMany = [users: User]
}

Grails creates a join table automatically. For production systems, an explicit join domain is the better choice.

The Join Domain Pattern

class UserRole {
    User user
    Role role

    static mapping = {
        id composite: ['user', 'role']
        version false
    }
}

A join domain gives you better control, easier querying, and improved performance.

Lazy vs Eager Fetching

Grails defaults to lazy loading:

static mapping = {
    books lazy: true
    books fetch: 'join'   // eager, use carefully
}

Eager fetching hurts performance when misused - prefer joins or explicit queries instead.

Validation in Relationships

class Book {
    Author author
    static constraints = {
        author nullable: false
    }
}

Querying Relationships

Book.findAllByAuthor(author)

def books = Book.where {
    author.name == "John"
}.list()

Common Mistakes

  • Missing belongsTo and losing cascade behavior.
  • Overusing many-to-many when a join domain fits better.
  • Ignoring lazy loading and N+1 queries.
  • Not indexing foreign-key columns.

Key Points

  • hasOne/hasMany belongTo cover the classic relationship shapes.
  • Use join domains for many-to-many in production.
  • Default to lazy fetching; use joins deliberately.
  • Validate relationships to keep data integrity.

GORM Relationships diagram

Share this post:

Comments (0)

Please login or register to comment.