(Quick Reference)

2 Getting Started

Version: 2023.3.0-SNAPSHOT

2 Getting Started

To use GORM {pluginVersion} for Hibernate in Grails 3 you can specify the following configuration in build.gradle:

dependencies {
    compile "org.grails.plugins:hibernate5:{pluginVersion}"
    compile "org.hibernate:hibernate-ehcache"
}

If you are using a version of Grails 3 earlier than 3.3 then you may need to enforce the GORM version. If you are using Grails 3.2.7 or above this can be done by modifying the gormVersion setting in gradle.properties:

gormVersion=2023.3.0-SNAPSHOT

Otherwise if you are using an earlier version of Grails you can force the GORM version by adding the following block directly above the dependencies block:

build.gradle
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if( details.requested.group == 'org.grails' &&
            details.requested.name.startsWith('grails-datastore')) {
            details.useVersion("2023.3.0-SNAPSHOT")
        }
    }
}
dependencies {
    ...
}

2.1 Common Problems

If you receive an error that indicates a failure to resolve the grails-datastore-simple dependency you may need to add the following to build.gradle directly above the dependencies block:

build.gradle
configurations.all {
    exclude module:'grails-datastore-simple'
}

2.2 Configuring Different Hibernate Versions

There are various changes you have to make to your build depending on the version of Grails when using GORM 2023.3.0-SNAPSHOT.

Grails 3.2.x and above with Hibernate 4

Grails 3.2.x is based on Spring Boot 1.4.x which enforces Hibernate 5.0.x as the default version. If you want to continue to use Hibernate 4 you must explicitly declare the Hibernate 4 dependences in build.gradle.

build.gradle
dependencies {
    compile "org.grails.plugins:hibernate4"
    compile "org.hibernate:hibernate-core:4.3.10.Final"
    compile "org.hibernate:hibernate-ehcache:4.3.10.Final"
}

Grails 3.1.x and below with Hibernate 5

Grails 3.1.x and below are based on Spring Boot 1.3.x which enforces Hibernate 4 as the default version of Hibernate, hence you have to use explicit versions to depend on Hibernate 5:

build.gradle
dependencies {
    compile "org.grails.plugins:hibernate5"
    compile "org.hibernate:hibernate-core:5.1.0.Final"
    compile "org.hibernate:hibernate-ehcache:5.1.0.Final"
}

Grails 3.0.x Spring Version Conflicts

Grails 3.0.x enforces Spring 4.1.x as the Spring version, so if you want to use Hibernate 5 you must force an upgrade to Spring 4.2.x in build.gradle:

build.gradle
// the below is unnecessary in Grails 3.1 and above, but required in Grails 3.0.x
configurations.all {
    resolutionStrategy {
        eachDependency { DependencyResolveDetails details ->
            if(details.requested.group == 'org.springframework') {
                details.useVersion('4.2.3.RELEASE')
            }
        }
    }
}

The resolutionStrategy is needed to enforce an upgrade to Spring 4.2.x which is required by Hibernate 5 support. This block is not needed if you are using Grails 3.1 or above.

2.3 Using GORM in Spring Boot

To use GORM for Hibernate in Spring Boot add the necessary dependencies to your Boot application:

compile("org.grails:gorm-hibernate5-spring-boot:2023.3.0-SNAPSHOT")
compile "org.hibernate:hibernate-core"
compile "org.hibernate:hibernate-ehcache"
runtime "com.h2database:h2:1.4.192"
// for MySQL
// runtime "mysql:mysql-connector-java"

// for connection pooling
runtime "org.apache.tomcat:tomcat-jdbc:8.5.0"
runtime "org.apache.tomcat.embed:tomcat-embed-logging-log4j:8.5.0"

Then ensure you have configured a datasource and Hibernate as per the Spring Boot guide. For example in the case of MySQL:

hibernate:
    hbm2ddl:
        auto: update
    dialect: org.hibernate.dialect.MySQL5InnoDBDialect
spring:
    datasource:
        driverClassName: com.mysql.jdbc.Driver
        url:   jdbc:mysql://127.0.0.1:3306/gorm
        username: root
        password: ""
If if you prefer to use the Grails way of configuring the DataSource (with dataSource.url etc.) then you can add @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration) to your Application class, which will allow GORM to take over configuring the data source.

Ensure your Boot Application class is annotated with ComponentScan, for example:

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.*

@Configuration
@EnableAutoConfiguration
@ComponentScan
class Application {
    static void main(String[] args) {
        SpringApplication.run Application, args
    }
}
Using ComponentScan without a value results in Boot scanning for classes in the same package or any package nested within the Application class package. If your GORM entities are in a different package specify the package name as the value of the ComponentScan annotation.

Finally create your GORM entities and ensure they are annotated with grails.persistence.Entity:

import grails.persistence.*

@Entity
class Person {
    String firstName
    String lastName
}

Note that Spring Boot does not include any kind of OpenSessionInView interceptor so if you try and invoke GORM methods in a Spring @Controller you may encounter a session not found error. To eliminate this problem make sure your @Controller methods are annotated with @Transactional. For example:

import org.springframework.transaction.annotation.Transactional
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
class PersonController {

    @RequestMapping("/people")
    @Transactional(readOnly = true)
    public List<String> people() {
        Person.list().collect { Person p ->
            "$p.firstName $p.lastName".toString()
        }
    }
}

In addition, if you wish to return a GORM instance from a Spring @Controller, it should be noted that Spring uses Jackson for JSON marshalling, and Jackson will attempt to marshal the entire object to JSON, which can present an issue since GORM adds additional persistence related properties to your domain instance. To resolve this issue you should use @JsonIgnoreProperties on your GORM entity class to ignore any properties added by GORM:

import grails.persistence.*
import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@Entity
@JsonIgnoreProperties(['dirtyPropertyNames', 'errors', 'dirty', 'attached', 'version'])
class Person {
    String firstName
    String lastName
}

2.4 Using GORM for Hibernate Outside Grails

If you wish to use GORM for Hibernate outside of a Grails application you should declare the necessary dependencies for GORM and the database you are using, for example in Gradle:

compile "org.grails:grails-datastore-gorm-hibernate5:2023.3.0-SNAPSHOT"
runtime "com.h2database:h2:1.4.192"
runtime "org.apache.tomcat:tomcat-jdbc:8.5.0"
runtime "org.apache.tomcat.embed:tomcat-embed-logging-log4j:8.5.0"
runtime "org.slf4j:slf4j-api:1.7.10"
The above example also uses the H2 Database and Tomcat connection pool. However other pool implementations are supported including commons-dbcp, tomcat pool or hikari. If a connection pool is not specified org.springframework.jdbc.datasource.DriverManagerDataSource is used, which creates a new connection to the database each time you request a connect. The latter will probably cause issues with an H2 in-memory database in that it will create a new in-memory database each time a connection is requested, losing previously created tables. Normal databases (MySql, Postgres or even file-based H2) are not affected.

Then create your entities in the src/main/groovy directory and annotate them with the grails.gorm.annotation.Entity annotation:

@Entity
class Person implements GormEntity<Person> { (1)
    String firstName
    String lastName
    static constraints = {
        firstName blank:false
        lastName blank:false
    }
}
1 Use of GormEntity is merely to aid IDE support outside of Grails. When used inside a Grails context, some IDEs will use the app/domain location as a hint to enable code completion.

Then you need to place the bootstrap logic somewhere in your application which uses HibernateDatastore:

import org.grails.orm.hibernate.HibernateDatastore
Map configuration = [
    'hibernate.hbm2ddl.auto':'create-drop',
    'dataSource.url':'jdbc:h2:mem:myDB'
]
HibernateDatastore datastore = new HibernateDatastore( configuration, Person)

For more information on how to configure GORM see the Configuration section.