CRUD Operations in Grails

Harry · 13 Sep 2026 · 2 views

The Four Operations

Almost every application revolves around Create, Read, Update, and Delete. With GORM these are trivial, and with services, validation, and transactions they stay correct at scale.

Create

def user = new User(
    username: "admin",
    email: "admin@example.com"
)
user.save()

The object exists in memory until save() persists it. save() runs validation automatically, and by default errors are ignored unless you check them - use failOnError: true during development:

user.save(failOnError: true)

Read

def user = User.get(1)              // null if missing
def byName = User.findByUsername("admin")
def all = User.list()
def page = User.list(max: 10, offset: 0)

Pagination is essential for performance; never list an entire table.

Update

def user = User.get(1)
user.email = "new@email.com"
user.save()

GORM tracks changes via dirty checking, so only modified fields are written. Partial updates from forms can use:

user.properties = params
user.save()

Delete

def user = User.get(1)
user.delete()

Prefer a soft delete in enterprise systems:

class User {
    Boolean deleted = false
}
user.deleted = true
user.save()

Transactions

Services are transactional by default, so multi-step operations either all succeed or all roll back:

class UserService {
    def createUser(Map params) {
        new User(params).save(failOnError: true)
    }
}

For manual control use withTransaction:

User.withTransaction { status ->
    def user = new User(username: "admin")
    user.save()
    status.setRollbackOnly()
}

Any runtime exception thrown inside a transaction triggers rollback automatically.

Thin Controllers

class UserController {
    UserService userService

    def save() {
        userService.createUser(params)
        redirect action: "index"
    }
}

Understand CTL Best Practices

  • Keep controllers thin and services rich.
  • Always paginate large datasets.
  • Prefer soft deletes.
  • Validate before saving; handle errors gracefully in the UI.

Key Points

  • save/list/get/findBy cover CRUD cleanly.
  • failOnError and errors make validation visible.
  • Services are transactional by default.
  • Prefers soft deletes in production systems.
Share this post:

Comments (0)

Please login or register to comment.