Friday, July 12, 2013

Default Value for Properties in Grails Domain Classes

Grails 2.2 has a new feature that allows you to set a default value for a domain class property, as you normally would do in the database. I can't find much (any) documentation about this feature at this point other than a couple stackoverflow posts and this JIRA.

This is a really useful feature because, even though I am working with a legacy Oracle schema and have the default values specified on those tables, my integration tests use the internal h2 database with the tables generated by Hibernate from my domain classes. Without being able to specify default values in my domain classes, I am stuck always having to insert all values into my tables even if they aren't important for my integration tests.

The syntax for specifying default value is very simple and goes in the mapping block:

static mapping = {
    myField defaultValue: "'foo'"
}

Note that you need the double quotes *and* single quotes or the DDL to generate the column will not have the correct syntax. If you only specified defaultValue: 'foo' for instance, the resulting DDL would be the following:
my_field varchar(100) default foo not null

You would therefore receive this error:
hbm2ddl.SchemaUpdate  - Column "FOO" not found

By putting both double and single quotes, like defaultValue: "'foo'", you get the correct DDL:
my_field varchar(100) default 'foo' not null

For numeric values, you also need quotes around the default value or the DDL for the default value does not even get generated. For example:

static mapping = {
    myIntegerField defaultValue: "1"
}

I have several fields that are mapped to enums, and unfortunately Grails does not seem to respect the defaultValue at all for those fields, at least in the version I am using (2.2.3). But since most of my fields with default values are either Strings or numbers this feature helps quite a bit!

4 comments:

  1. Just set the values in the domain class.

    class myApi {

    String myUrl = "http://foo.com:8080/"
    String myVersion = "5.15"
    String cabin = "ECONOMY"

    }

    From my understanding defaultValue: no longer works and it does not work for me in 2.2.5

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. UnknownApril 18, 2018 at 9:10 AM
    Thank you for such a great syntactical help. For me defaultValue doesn't seems to work in 2.3.8.
    My code:
    version column: 'APPL_VERSION', defaultValue:"0"

    It doesn't take this value while I try to persist data into this table by:
    object.save(flush:true)

    It give error: field version is not null. Could you help me with it?

    ReplyDelete
    Replies
    1. That should work, but I don't have access to 2.3.8. "version" is a magic column in domain classes, so that may be causing problems. Grails will automatically create and manage a "version" column to handle concurrent update logic. If you are redefining its data type or something like that, it could be the problem. Maybe try the same thing with a different property and see if it works. Best -Ed

      Delete