(Quick Reference)

15. Grails and Hibernate - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: 1.4.0.M1

15. Grails and Hibernate

If GORM (Grails Object Relational Mapping) is not flexible enough for your liking you can alternatively map your domain classes using Hibernate, either via XML mapping files or JPA annotations. You will be able to map Grails domain classes onto a wider range of legacy systems and be more flexible in the creation of your database schema. Best of all, you will still be able to call all of the dynamic persistent and query methods provided by GORM!

15.1 Using Hibernate XML Mapping Files

Mapping your domain classes via XML is pretty straightforward. Simply create a hibernate.cfg.xml file in your project's grails-app/conf/hibernate directory, either manually or via the create-hibernate-cfg-xml command, that contains the following:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Example mapping file inclusion -->
        <mapping resource="org.example.Book.hbm.xml"/></session-factory>
</hibernate-configuration>

The individual mapping files, like 'org.example.Book.hbm.xml' in the above example, also go into the grails-app/conf/hibernate directory. To find out how to map domain classes via XML, check out the Hibernate manual.

If the default location of the hibernate.cfg.xml file doesn't suit you, you can change it by specifying an alternative location in grails-app/conf/DataSource.groovy:

hibernate {
    config.location = "file:/path/to/my/hibernate.cfg.xml"
}

or even a list of locations:

hibernate {
    config.location = ["file:/path/to/one/hibernate.cfg.xml", "file:/path/to/two/hibernate.cfg.xml"]
}

Grails also allows you to write your domain model in Java or re-use an existing one that already has Hibernate mapping files. Simply place the mapping files into grails-app/conf/hibernate and either put the Java files in src/java or (if the domain model is stored in a JAR) the packaged classes into the project's lib directory. You still need the hibernate.cfg.xml though!

15.2 Mapping with Hibernate Annotations

To map a domain class via annotations, create a new class in src/java and use the annotations defined as part of the EJB 3.0 spec (for more info on this see the Hibernate Annotations Docs):

package com.books;
@Entity
public class Book {
    private Long id;
    private String title;
    private String description;
    private Date date;

@Id @GeneratedValue public Long getId() { return id; }

public void setId(Long id) { this.id = id; }

public String getTitle() { return title; }

public void setTitle(String title) { this.title = title; }

public String getDescription() { return description; }

public void setDescription(String description) { this.description = description; } }

Once that is done you need to register the class with the Hibernate sessionFactory by adding relevant entries to the grails-app/conf/hibernate/hibernate.cfg.xml file as follows:

<!DOCTYPE hibernate-configuration SYSTEM
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <mapping package="com.books" />
        <mapping class="com.books.Book" />
    </session-factory>
</hibernate-configuration>
See the previous section for more information on the hibernate.cfg.xml file.

When Grails loads it will register the necessary dynamic methods with the class. To see what else you can do with a Hibernate domain class see the section on Scaffolding.

15.3 Adding Constraints

Even if you use a Java domain model, you can still take advantage of GORM validation. Grails allows you to define constraints through a separate script that you place in the src/java directory. The script should be in a directory that matches the package of the corresponding domain class and its name should have a Constraints suffix. For example, if you had a domain class org.example.Book, then you would create the script src/java/org/example/BookConstraints.groovy.

The contents of the script should contain a standard GORM constraints block like so:

constraints = {
    title(blank: false)
    author(blank: false)
}
Once the script is in place, you'll be able to validate instances of your domain class!

15.4 Further Reading

Grails committer, Jason Rudolph, took the time to write many useful articles about using Grails with custom Hibernate mappings including: