7.5.2 Custom ORM Mapping 3.1.7

See the light - agile, industrial strength, rapid web application development made easy

(Quick Reference) # 7.5.2 Custom ORM Mapping - Reference Documentation Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari Version: 3.1.7 ## Table of Contents ## 7.5.2 Custom ORM Mapping Grails domain classes can be mapped onto many legacy schemas with an Object Relational Mapping DSL (domain specific language). The following sections takes you through what is possible with the ORM DSL. None of this is necessary if you are happy to stick to the conventions defined by GORM for table names, column names and so on. You only needs this functionality if you need to tailor the way GORM maps onto legacy schemas or configures caching Custom mappings are defined using a static `mapping` block defined within your domain class:
    class Person {
        …
        static mapping = {
            version false
            autoTimestamp false
        }
    }
You can also configure global mappings in `application.groovy` (or an external config file) using this setting:
    grails.gorm.default.mapping = {
        version false
        autoTimestamp false
    }
It has the same syntax as the standard `mapping` block but it applies to all your domain classes! You can then override these defaults within the `mapping` block of a domain class. ## 7.5.2.1 Table and Column Names #### Table names The database table name which the class maps to can be customized using the `table` method:
    class Person {
        …
        static mapping = {
            table 'people'
        }
    }
In this case the class would be mapped to a table called `people` instead of the default name of `person`. #### Column names It is also possible to customize the mapping for individual columns onto the database. For example to change the name you can do:

    class Person {    String firstName    static mapping = {
            table 'people'
            firstName column: 'First_Name'
        }
    }
Here `firstName` is a dynamic method within the `mapping` Closure that has a single Map parameter. Since its name corresponds to a domain class persistent field, the parameter values (in this case just `"column"`) are used to configure the mapping for that property. #### Column type GORM supports configuration of Hibernate types with the DSL using the type attribute. This includes specifying user types that implement the Hibernate org.hibernate.usertype.UserType interface, which allows complete customization of how a type is persisted. As an example if you had a `PostCodeType` you could use it as follows:

    class Address {    String number
        String postCode    static mapping = {
            postCode type: PostCodeType
        }
    }
Alternatively if you just wanted to map it to one of Hibernate's basic types other than the default chosen by Grails you could use:

    class Address {    String number
        String postCode    static mapping = {
            postCode type: 'text'
        }
    }
This would make the `postCode` column map to the default large-text type for the database you're using (for example TEXT or CLOB). See the Hibernate documentation regarding Basic Types for further information. #### Many-to-One/One-to-One Mappings In the case of associations it is also possible to configure the foreign keys used to map associations. In the case of a many-to-one or one-to-one association this is exactly the same as any regular column. For example consider the following:

    class Person {    String firstName
        Address address    static mapping = {
            table 'people'
            firstName column: 'First_Name'
            address column: 'Person_Address_Id'
        }
    }
By default the `address` association would map to a foreign key column called `address_id`. By using the above mapping we have changed the name of the foreign key column to `Person_Adress_Id`. #### One-to-Many Mapping With a bidirectional one-to-many you can change the foreign key column used by changing the column name on the many side of the association as per the example in the previous section on one-to-one associations. However, with unidirectional associations the foreign key needs to be specified on the association itself. For example given a unidirectional one-to-many relationship between `Person` and `Address` the following code will change the foreign key in the `address` table:

    class Person {    String firstName    static hasMany = [addresses: Address]    static mapping = {
            table 'people'
            firstName column: 'First_Name'
            addresses column: 'Person_Address_Id'
        }
    }
If you don't want the column to be in the `address` table, but instead some intermediate join table you can use the `joinTable` parameter:

    class Person {    String firstName    static hasMany = [addresses: Address]    static mapping = {
            table 'people'
            firstName column: 'First_Name'
            addresses joinTable: [name: 'Person_Addresses',
                                  key: 'Person_Id',
                                  column: 'Address_Id']
        }
    }
#### Many-to-Many Mapping Grails, by default maps a many-to-many association using a join table. For example consider this many-to-many association:
    class Group {
        …
        static hasMany = [people: Person]
    }
    class Person {
        …
        static belongsTo = Group
        static hasMany = [groups: Group]
    }
In this case Grails will create a join table called `group_person` containing foreign keys called `person_id` and `group_id` referencing the `person` and `group` tables. To change the column names you can specify a column within the mappings for each class.
    class Group {
       …
       static mapping = {
           people column: 'Group_Person_Id'
       }
    }
    class Person {
       …
       static mapping = {
           groups column: 'Group_Group_Id'
       }
    }
You can also specify the name of the join table to use:
    class Group {
       …
       static mapping = {
           people column: 'Group_Person_Id',
                  joinTable: 'PERSON_GROUP_ASSOCIATIONS'
       }
    }
    class Person {
       …
       static mapping = {
           groups column: 'Group_Group_Id',
                  joinTable: 'PERSON_GROUP_ASSOCIATIONS'
       }
    }
## 7.5.2.2 Caching Strategy #### Setting up caching Hibernate features a second-level cache with a customizable cache provider. This needs to be configured in the `grails-app/conf/application.yml` file as follows:
    hibernate:
      cache:
        use_second_level_cache: true
        provider_class: net.sf.ehcache.hibernate.EhCacheProvider
        region:
           factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
You can customize any of these settings, for example to use a distributed caching mechanism. For further reading on caching and in particular Hibernate's second-level cache, refer to the Hibernate documentation on the subject. #### Caching instances Call the `cache` method in your mapping block to enable caching with the default settings:
    class Person {
        …
        static mapping = {
            table 'people'
            cache true
        }
    }
This will configure a 'read-write' cache that includes both lazy and non-lazy properties. You can customize this further:
    class Person {
        …
        static mapping = {
            table 'people'
            cache usage: 'read-only', include: 'non-lazy'
        }
    }
#### Caching associations As well as the ability to use Hibernate's second level cache to cache instances you can also cache collections (associations) of objects. For example:

    class Person {    String firstName    static hasMany = [addresses: Address]    static mapping = {
            table 'people'
            version false
            addresses column: 'Address', cache: true
        }
    }
    class Address {
        String number
        String postCode
    }
This will enable a 'read-write' caching mechanism on the `addresses` collection. You can also use:
    cache: 'read-write' // or 'read-only' or 'transactional'
to further configure the cache usage. #### Caching Queries You can cache queries such as dynamic finders and criteria. To do so using a dynamic finder you can pass the `cache` argument:
    def person = Person.findByFirstName("Fred", [cache: true])
In order for the results of the query to be cached, you must enable caching in your mapping as discussed in the previous section. You can also cache criteria queries:
    def people = Person.withCriteria {
        like('firstName', 'Fr%')
        cache true
    }
#### Cache usages Below is a description of the different cache settings and their usages: `read-only` - If your application needs to read but never modify instances of a persistent class, a read-only cache may be used. `read-write` - If the application needs to update data, a read-write cache might be appropriate. `nonstrict-read-write` - If the application only occasionally needs to update data (i.e. if it is very unlikely that two transactions would try to update the same item simultaneously) and strict transaction isolation is not required, a `nonstrict-read-write` cache might be appropriate. `transactional` - The `transactional` cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. Such a cache may only be used in a JTA environment and you must specify `hibernate.transaction.manager_lookup_class` in the `grails-app/conf/application.groovy` file's `hibernate` config. ## 7.5.2.3 Inheritance Strategies By default GORM classes use `table-per-hierarchy` inheritance mapping. This has the disadvantage that columns cannot have a `NOT-NULL` constraint applied to them at the database level. If you would prefer to use a `table-per-subclass` inheritance strategy you can do so as follows:

    class Payment {
        Integer amount    static mapping = {
            tablePerHierarchy false
        }
    }class CreditCardPayment extends Payment {
        String cardNumber
    }
The mapping of the root `Payment` class specifies that it will not be using `table-per-hierarchy` mapping for all child classes. ## 7.5.2.4 Custom Database Identity You can customize how GORM generates identifiers for the database using the DSL. By default GORM relies on the native database mechanism for generating ids. This is by far the best approach, but there are still many schemas that have different approaches to identity. To deal with this Hibernate defines the concept of an id generator. You can customize the id generator and the column it maps to as follows:
    class Person {
        …
        static mapping = {
            table 'people'
            version false
            id generator: 'hilo',
               params: [table: 'hi_value',
                        column: 'next_value',
                        max_lo: 100]
        }
    }
In this case we're using one of Hibernate's built in 'hilo' generators that uses a separate table to generate ids. For more information on the different Hibernate generators refer to the Hibernate reference documentation Although you don't typically specify the `id` field (Grails adds it for you) you can still configure its mapping like the other properties. For example to customise the column for the id property you can do:
    class Person {
        …
        static mapping = {
            table 'people'
            version false
            id column: 'person_id'
        }
    }
## 7.5.2.5 Composite Primary Keys GORM supports the concept of composite identifiers (identifiers composed from 2 or more properties). It is not an approach we recommend, but is available to you if you need it:

    import org.apache.commons.lang.builder.HashCodeBuilderclass Person implements Serializable {    String firstName
        String lastName    boolean equals(other) {
            if (!(other instanceof Person)) {
                return false
            }        other.firstName == firstName && other.lastName == lastName
        }    int hashCode() {
            def builder = new HashCodeBuilder()
            builder.append firstName
            builder.append lastName
            builder.toHashCode()
        }    static mapping = {
            id composite: ['firstName', 'lastName']
        }
    }
The above will create a composite id of the `firstName` and `lastName` properties of the Person class. To retrieve an instance by id you use a prototype of the object itself:
    def p = Person.get(new Person(firstName: "Fred", lastName: "Flintstone"))
    println p.firstName
Domain classes mapped with composite primary keys must implement the `Serializable` interface and override the `equals` and `hashCode` methods, using the properties in the composite key for the calculations. The example above uses a `HashCodeBuilder` for convenience but it's fine to implement it yourself. Another important consideration when using composite primary keys is associations. If for example you have a many-to-one association where the foreign keys are stored in the associated table then 2 columns will be present in the associated table. For example consider the following domain class:
    class Address {
        Person person
    }
In this case the `address` table will have an additional two columns called `person_first_name` and `person_last_name`. If you wish the change the mapping of these columns then you can do so using the following technique:
    class Address {
        Person person
        static mapping = {
            columns {
    		    person {
                    column name: "FirstName"
                    column name: "LastName"
    			}
            }
        }
    }
## 7.5.2.6 Database Indices To get the best performance out of your queries it is often necessary to tailor the table index definitions. How you tailor them is domain specific and a matter of monitoring usage patterns of your queries. With GORM's DSL you can specify which columns are used in which indexes:
    class Person {
        String firstName
        String address
        static mapping = {
            table 'people'
            version false
            id column: 'person_id'
            firstName column: 'First_Name', index: 'Name_Idx'
            address column: 'Address', index: 'Name_Idx,Address_Index'
        }
    }
Note that you cannot have any spaces in the value of the `index` attribute; in this example `index:'Name_Idx, Address_Index'` will cause an error. ## 7.5.2.7 Optimistic Locking and Versioning As discussed in the section on Optimistic and Pessimistic Locking, by default GORM uses optimistic locking and automatically injects a `version` property into every class which is in turn mapped to a `version` column at the database level. If you're mapping to a legacy schema that doesn't have version columns (or there's some other reason why you don't want/need this feature) you can disable this with the `version` method:
    class Person {
        …
        static mapping = {
            table 'people'
            version false
        }
    }
If you disable optimistic locking you are essentially on your own with regards to concurrent updates and are open to the risk of users losing data (due to data overriding) unless you use pessimistic locking #### Version columns types By default Grails maps the `version` property as a `Long` that gets incremented by one each time an instance is updated. But Hibernate also supports using a `Timestamp`, for example:

    import java.sql.Timestampclass Person {    …
        Timestamp version    static mapping = {
            table 'people'
        }
    }
There's a slight risk that two updates occurring at nearly the same time on a fast server can end up with the same timestamp value but this risk is very low. One benefit of using a `Timestamp` instead of a `Long` is that you combine the optimistic locking and last-updated semantics into a single column. ## 7.5.2.8 Eager and Lazy Fetching #### Lazy Collections As discussed in the section on Eager and Lazy fetching, GORM collections are lazily loaded by default but you can change this behaviour with the ORM DSL. There are several options available to you, but the most common ones are: lazy: false fetch: 'join' and they're used like this:

    class Person {    String firstName
        Pet pet    static hasMany = [addresses: Address]    static mapping = {
            addresses lazy: false
            pet fetch: 'join'
        }
    }
    class Address {
        String street
        String postCode
    }
    class Pet {
        String name
    }
The first option, `lazy: false` , ensures that when a `Person` instance is loaded, its `addresses` collection is loaded at the same time with a second SELECT. The second option is basically the same, except the collection is loaded with a JOIN rather than another SELECT. Typically you want to reduce the number of queries, so `fetch: 'join'` is the more appropriate option. On the other hand, it could feasibly be the more expensive approach if your domain model and data result in more and larger results than would otherwise be necessary. For more advanced users, the other settings available are: batchSize: N lazy: false, batchSize: N where N is an integer. These let you fetch results in batches, with one query per batch. As a simple example, consider this mapping for `Person`:

    class Person {    String firstName
        Pet pet    static mapping = {
            pet batchSize: 5
        }
    }
If a query returns multiple `Person` instances, then when we access the first `pet` property, Hibernate will fetch that `Pet` plus the four next ones. You can get the same behaviour with eager loading by combining `batchSize` with the `lazy: false` option. You can find out more about these options in the Hibernate user guide and this primer on fetching strategies. Note that ORM DSL does not currently support the "subselect" fetching strategy. #### Lazy Single-Ended Associations In GORM, one-to-one and many-to-one associations are by default lazy. Non-lazy single ended associations can be problematic when you load many entities because each non-lazy association will result in an extra SELECT statement. If the associated entities also have non-lazy associations, the number of queries grows significantly! Use the same technique as for lazy collections to make a one-to-one or many-to-one association non-lazy/eager:
    class Person {
        String firstName
    }

    class Address {    String street
        String postCode    static belongsTo = [person: Person]    static mapping = {
            person lazy: false
        }
    }
Here we configure GORM to load the associated `Person` instance (through the `person` property) whenever an `Address` is loaded. #### Lazy Single-Ended Associations and Proxies Hibernate uses runtime-generated proxies to facilitate single-ended lazy associations; Hibernate dynamically subclasses the entity class to create the proxy. Consider the previous example but with a lazily-loaded `person` association: Hibernate will set the `person` property to a proxy that is a subclass of `Person`. When you call any of the getters (except for the `id` property) or setters on that proxy, Hibernate will load the entity from the database. Unfortunately this technique can produce surprising results. Consider the following example classes:
    class Pet {
        String name
    }
    class Dog extends Pet {
    }
    class Person {
        String name
        Pet pet
    }
and assume that we have a single `Person` instance with a `Dog` as the `pet`. The following code will work as you would expect:
    def person = Person.get(1)
    assert person.pet instanceof Dog
    assert Pet.get(person.petId) instanceof Dog
But this won't:
    def person = Person.get(1)
    assert person.pet instanceof Dog
    assert Pet.list()[0] instanceof Dog
The second assertion fails, and to add to the confusion, this will work:
    assert Pet.list()[0] instanceof Dog
What's going on here? It's down to a combination of how proxies work and the guarantees that the Hibernate session makes. When you load the `Person` instance, Hibernate creates a proxy for its `pet` relation and attaches it to the session. Once that happens, whenever you retrieve that `Pet` instance with a query, a `get()`, or the `pet` relation within the same session , Hibernate gives you the proxy. Fortunately for us, GORM automatically unwraps the proxy when you use `get()` and `findBy*()`, or when you directly access the relation. That means you don't have to worry at all about proxies in the majority of cases. But GORM doesn't do that for objects returned with a query that returns a list, such as `list()` and `findAllBy*()`. However, if Hibernate hasn't attached the proxy to the session, those queries will return the real instances - hence why the last example works. You can protect yourself to a degree from this problem by using the `instanceOf` method by GORM:
    def person = Person.get(1)
    assert Pet.list()[0].instanceOf(Dog)
However, it won't help here if casting is involved. For example, the following code will throw a `ClassCastException` because the first pet in the list is a proxy instance with a class that is neither `Dog` nor a sub-class of `Dog`:
    def person = Person.get(1)
    Dog pet = Pet.list()[0]
Of course, it's best not to use static types in this situation. If you use an untyped variable for the pet instead, you can access any `Dog` properties or methods on the instance without any problems. These days it's rare that you will come across this issue, but it's best to be aware of it just in case. At least you will know why such an error occurs and be able to work around it. ## 7.5.2.9 Custom Cascade Behaviour As described in the section on cascading updates, the primary mechanism to control the way updates and deletes cascade from one association to another is the static belongsTo property. However, the ORM DSL gives you complete access to Hibernate's transitive persistence capabilities using the `cascade` attribute. Valid settings for the cascade attribute include: `merge` - merges the state of a detached association `save-update` - cascades only saves and updates to an association `delete` - cascades only deletes to an association `lock` - useful if a pessimistic lock should be cascaded to its associations `refresh` - cascades refreshes to an association `evict` - cascades evictions (equivalent to `discard()` in GORM) to associations if set `all` - cascade all operations to associations `all-delete-orphan` - Applies only to one-to-many associations and indicates that when a child is removed from an association then it should be automatically deleted. Children are also deleted when the parent is. It is advisable to read the section in the Hibernate documentation on transitive persistence to obtain a better understanding of the different cascade styles and recommendations for their usage To specify the cascade attribute simply define one or more (comma-separated) of the aforementioned settings as its value:

    class Person {    String firstName    static hasMany = [addresses: Address]    static mapping = {
            addresses cascade: "all-delete-orphan"
        }
    }
    class Address {
        String street
        String postCode
    }
## 7.5.2.10 Custom Hibernate Types You saw in an earlier section that you can use composition (with the `embedded` property) to break a table into multiple objects. You can achieve a similar effect with Hibernate's custom user types. These are not domain classes themselves, but plain Java or Groovy classes. Each of these types also has a corresponding "meta-type" class that implements org.hibernate.usertype.UserType. The Hibernate reference manual has some information on custom types, but here we will focus on how to map them in Grails. Let's start by taking a look at a simple domain class that uses an old-fashioned (pre-Java 1.5) type-safe enum class:

    class Book {    String title
        String author
        Rating rating    static mapping = {
            rating type: RatingUserType
        }
    }
All we have done is declare the `rating` field the enum type and set the property's type in the custom mapping to the corresponding `UserType` implementation. That's all you have to do to start using your custom type. If you want, you can also use the other column settings such as "column" to change the column name and "index" to add it to an index. Custom types aren't limited to just a single column - they can be mapped to as many columns as you want. In such cases you explicitly define in the mapping what columns to use, since Hibernate can only use the property name for a single column. Fortunately, Grails lets you map multiple columns to a property using this syntax:

    class Book {    String title
        Name author
        Rating rating    static mapping = {
            author type: NameUserType, {
                column name: "first_name"
                column name: "last_name"
            }
            rating type: RatingUserType
        }
    }
The above example will create "first_name" and "last_name" columns for the `author` property. You'll be pleased to know that you can also use some of the normal column/property mapping attributes in the column definitions. For example:
    column name: "first_name", index: "my_idx", unique: true
The column definitions do not support the following attributes: `type`, `cascade`, `lazy`, `cache`, and `joinTable`. One thing to bear in mind with custom types is that they define the SQL types for the corresponding database columns. That helps take the burden of configuring them yourself, but what happens if you have a legacy database that uses a different SQL type for one of the columns? In that case, override the column's SQL type using the `sqlType` attribute:

    class Book {    String title
        Name author
        Rating rating    static mapping = {
            author type: NameUserType, {
                column name: "first_name", sqlType: "text"
                column name: "last_name", sqlType: "text"
            }
            rating type: RatingUserType, sqlType: "text"
        }
    }
Mind you, the SQL type you specify needs to still work with the custom type. So overriding a default of "varchar" with "text" is fine, but overriding "text" with "yes_no" isn't going to work. ## 7.5.2.11 Derived Properties A derived property is one that takes its value from a SQL expression, often but not necessarily based on the value of one or more other persistent properties. Consider a Product class like this:
    class Product {
        Float price
        Float taxRate
        Float tax
    }
If the `tax` property is derived based on the value of `price` and `taxRate` properties then is probably no need to persist the `tax` property. The SQL used to derive the value of a derived property may be expressed in the ORM DSL like this:

    class Product {
        Float price
        Float taxRate
        Float tax    static mapping = {
            tax formula: 'PRICE * TAX_RATE'
        }
    }
Note that the formula expressed in the ORM DSL is SQL so references to other properties should relate to the persistence model not the object model, which is why the example refers to `PRICE` and `TAX_RATE` instead of `price` and `taxRate`. With that in place, when a Product is retrieved with something like `Product.get(42)`, the SQL that is generated to support that will look something like this:
    select
        product0_.id as id1_0_,
        product0_.version as version1_0_,
        product0_.price as price1_0_,
        product0_.tax_rate as tax4_1_0_,
        product0_.PRICE * product0_.TAX_RATE as formula1_0_
    from
        product product0_
    where
        product0_.id=?
Since the `tax` property is derived at runtime and not stored in the database it might seem that the same effect could be achieved by adding a method like `getTax()` to the `Product` class that simply returns the product of the `taxRate` and `price` properties. With an approach like that you would give up the ability query the database based on the value of the `tax` property. Using a derived property allows exactly that. To retrieve all `Product` objects that have a `tax` value greater than 21.12 you could execute a query like this:
    Product.findAllByTaxGreaterThan(21.12)
Derived properties may be referenced in the Criteria API:
    Product.withCriteria {
        gt 'tax', 21.12f
    }
The SQL that is generated to support either of those would look something like this:
    select
        this_.id as id1_0_,
        this_.version as version1_0_,
        this_.price as price1_0_,
        this_.tax_rate as tax4_1_0_,
        this_.PRICE * this_.TAX_RATE as formula1_0_
    from
        product this_
    where
        this_.PRICE * this_.TAX_RATE>?
Because the value of a derived property is generated in the database and depends on the execution of SQL code, derived properties may not have GORM constraints applied to them. If constraints are specified for a derived property, they will be ignored. ## 7.5.2.12 Custom Naming Strategy By default Grails uses Hibernate's `ImprovedNamingStrategy` to convert domain class Class and field names to SQL table and column names by converting from camel-cased Strings to ones that use underscores as word separators. You can customize these on a per-class basis in the `mapping` closure but if there's a consistent pattern you can specify a different `NamingStrategy` class to use. Configure the class name to be used in `grails-app/conf/application.groovy` in the `hibernate` section, e.g.

    dataSource {
        pooled = true
        dbCreate = "create-drop"
        …
    }hibernate {
        cache.use_second_level_cache = true
        …
        naming_strategy = com.myco.myproj.CustomNamingStrategy
    }
You can also specify the name of the class and it will be loaded for you:
    hibernate {
        …
        naming_strategy = 'com.myco.myproj.CustomNamingStrategy'
    }
A third option is to provide an instance if there is some configuration required beyond calling the default constructor:
    hibernate {
        …
        def strategy = new com.myco.myproj.CustomNamingStrategy()
        // configure as needed
        naming_strategy = strategy
    }
You can use an existing class or write your own, for example one that prefixes table names and column names:

    package com.myco.myprojimport org.hibernate.cfg.ImprovedNamingStrategy
    import org.hibernate.util.StringHelperclass CustomNamingStrategy extends ImprovedNamingStrategy {    String classToTableName(String className) {
            "table_" + StringHelper.unqualify(className)
        }    String propertyToColumnName(String propertyName) {
            "col_" + StringHelper.unqualify(propertyName)
        }
    }
| Quick Reference (hide)