<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0' xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <channel>
    <title>Wolfmans Howlings: Using Postgresql with Grails</title>
    <link>http://blog.wolfman.com/articles/2009/11/11/using-postgresql-with-grails</link>
    <description>A programmers Blog about Ruby, Rails and a few other issue</description>
    <language>en-us</language>
    <ttl>40</ttl>
    <item>
      <title>Using Postgresql with Grails</title>
      <description>
        &lt;p&gt;I started playing with Grails, and I am planning to rewrite the blog
        engine I use for this blog in Grails. As noted
        &lt;a href=&quot;http://blog.wolfman.com/articles/2009/1/13/new-merb-based-blog&quot;&gt;earlier&lt;/a&gt;
        I wrote it in Merb originally. Although Merb is nice and lite it seems
        to be having difficulty keeping up with the gems it is dependent on. A
        case in point is Cucumber which it says is its recommended way of
        doing integration tests. The current version of Cucumber is very
        difficult to get working with Merb. See the
        &lt;a href=&quot;http://github.com/wolfmanjm/wolfmanblog&quot;&gt;Git source&lt;/a&gt; to see how I
        finally did it.&lt;/p&gt;
        
        &lt;p&gt;While I was learning Grails, I hooked up Postgresql 8.2 to Grails
        using the &lt;code&gt;Datasource.groovy&lt;/code&gt; file. I turned on SQL logging, and to my
        horror saw how it was handling the id's. I have been using Postgresql
        for quite a while now, and used to run into problems with the creation
        and retrieval of the automatically generated IDs. It seems a lot of
        people run into these hard to describe problems, as it appears to
        happen rarely and is probably a race condition. With version &gt;= 8.2
        Postgresql introduced a way of inserting a new record and returning
        the automatically generated id in one atomic statement. This solves
        all the problems and is more efficient as it does not require two
        queries for each insert.&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;insert into users (version, crypted_password, admin, name, date_created, salt)
        values (?, ?, ?, ?, ?, ?) RETURNING id
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;For id when it has this schema&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;id | bigint | not null default nextval('users_id_seq'::regclass)
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;The &lt;code&gt;RETURNING id&lt;/code&gt; is the trick here.&lt;/p&gt;
        
        &lt;p&gt;By default Hibernate, which is the underlying ORM used by GORM, which
        is the Grails ORM, seems to use a sequence to generate the next id
        then write the id in the INSERT SQL statement.&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;select nextval ('hibernate_sequence')
        
        insert into users (version, crypted_password, admin, name, date_created, salt, id)
        values (?, ?, ?, ?, ?, ?, ?)
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;This sequence should work in most cases, as &lt;code&gt;nextval&lt;/code&gt; is supposed to
        be atomic and should return a unique sequence regardless of how many
        threads are concurrently accessing the database, however I have
        &lt;a href=&quot;https://forum.hibernate.org/viewtopic.php?p=2385225&quot;&gt;read&lt;/a&gt; that this
        causes problems in Hibernate and in Grails a
        &lt;a href=&quot;http://jira.codehaus.org/browse/GRAILS-2662&quot;&gt;bug&lt;/a&gt; was filed saying
        that this causes problems in Grails if you are doing inserts during
        the bootstrap process, something to do with the way Hibernate caches
        or batches stuff.&lt;/p&gt;
        
        &lt;p&gt;If you force hibernate to use the identity method of sequences 
        &lt;code&gt;id generator:'identity'&lt;/code&gt; which is the preferred method anyway, then
        Hibernate uses this sequence to get the id after an insert...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;insert into users (version, crypted_password, admin, name, date_created, salt)
        values (?, ?, ?, ?, ?, ?)
        
        select currval('users_id_seq')
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Now I know that this sequence (other than being inefficient) can be
        subject to a race condition where the id returned is not the id that
        was just generated. I do not know why as Postgresql says it should
        work, but I have actually been bitten by that on occasion in
        production, and it was solved by using &lt;code&gt;RETURNING id&lt;/code&gt;.&lt;/p&gt;
        
        &lt;p&gt;So I was surprised that the current version of Hibernate does not use
        the currently recommended way of doing this common sequence. However
        it does provide a way to work around the problem. This solution really
        only works in Grails, because you have to hard code the column used
        for the id, if the API in Hibernate was a little more flexible it
        could be made generic, but that is an issue for the Hibernate JIRA.&lt;/p&gt;
        
        &lt;p&gt;Anyway here is the solution for Grails.&lt;/p&gt;
        
        &lt;p&gt;First stick this file in
        &lt;code&gt;GRAILS_PROJECT/src/java/com/e4net/hibernate/dialect/PostgreSQL82Dialect.java&lt;/code&gt;&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;package com.e4net.hibernate.dialect;
        
        import org.hibernate.dialect.PostgreSQLDialect;
        
        public class PostgreSQL82Dialect extends PostgreSQLDialect {
        
            public PostgreSQL82Dialect() {
        
            }
        
            public boolean supportsInsertSelectIdentity() {
                    return true;
            }
        
            public String appendIdentitySelectToInsert(String insertString) {
                    return insertString + &quot; RETURNING id&quot;;
            }
        }
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;This sets up a extension to the standard Postgresql dialect that
        Hibernate uses. It tells Hibernate that the id can be returned in the
        same SQL statement of the INSERT, and also how to modify the insert
        SQL statement to do that. This is where &lt;code&gt;id&lt;/code&gt; is hard coded, if we were
        passed a little more information like what the identity column was we
        could make this generic.&lt;/p&gt;
        
        &lt;p&gt;Then in your &lt;code&gt;GRAILS_PROJECT/grails-app/conf/DataSource.groovy&lt;/code&gt;&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;            dataSource {
                            dbCreate = &quot;update&quot; // one of 'create', 'create-drop','update'
                            url = &quot;jdbc:postgresql://localhost/wolfmanblog_dev&quot;
                            driverClassName = &quot;org.postgresql.Driver&quot;
                            dialect = 'com.e4net.hibernate.dialect.PostgreSQL82Dialect'
                            logSql = true
                            username = &quot;xxxx&quot;
                            password = &quot;xxxx&quot;
                    }
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Note the &lt;code&gt;dialect = 'com.e4net.hibernate.dialect.PostgreSQL82Dialect'&lt;/code&gt;
        this tells it to use the class we created above.&lt;/p&gt;
        
        &lt;p&gt;Now we need to tell Hibernate to always use the &lt;code&gt;identity&lt;/code&gt; method for
        generating ids. This can be done in the static mapping stanza in each
        of your domain classes...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;static mapping = {
            id generator: 'identity'
        }
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Or if you are using Grails 1.2-M4 or better you can put this in
        &lt;code&gt;GRAILS_PROJECT/grails-app/conf/Config.groovy&lt;/code&gt;&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;grails.gorm.default.mapping = {
            id generator:'identity'
        }
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Which will change the default for all your domain classes.&lt;/p&gt;
        
        &lt;p&gt;Now when you do an insert you will get this...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;insert into users (version, crypted_password, admin, name, date_created, salt)
        values (?, ?, ?, ?, ?, ?) RETURNING id
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Which is more efficient and correct.&lt;/p&gt;
        
        &lt;p&gt;I'd like to see this in the default Hibernate Postgresql
        dialect, maybe it could determine the version of Postgresql it is
        using and do the correct thing?&lt;/p&gt;
        
        &lt;p&gt;&lt;a href=&quot;http://technorati.com/tag/hibernate+postgresql&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;
        &lt;a href=&quot;http://technorati.com/tag/grails+postgresql&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;&lt;/p&gt;
      </description>
      <author>Jim Morris</author>
      <pubDate>Wed, 11 Nov 2009 14:11:41 -0800</pubDate>
      <link>http://blog.wolfman.com/articles/2009/11/11/using-postgresql-with-grails</link>
      <guid isPermaLink='false'>urn:uuid:27f65e3e-de89-43da-b4c7-907be49dc749</guid>
    </item>
    <item>
      <title>"Using Postgresql with Grails" by Fletch</title>
      <description>Thanks for this. Detailed instructions. Sounds great and I'll look to try it out in due course.</description>
      <pubDate>Thu, 12 Nov 2009 00:31:08 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/50#comment-283</link>
      <guid isPermaLink='false'>urn:uuid:514c99a5-203e-45d4-9bf5-f7a2d188102c</guid>
    </item>
    <item>
      <title>"Using Postgresql with Grails" by seanoc5</title>
      <description>
        Ah, Wolfman, this is good. I thought I was out in the crazy wilderness trying to use postgresql with grails (or hibernate, or most other popular frameworks). This certainly helps me.
        
        I still have some general strategy/performance questions, but will try my luck on the grails mailing list. 
        
        Many thanks for writing this up, well worth the read.
        +1
        
        Sean
      </description>
      <pubDate>Wed, 18 Nov 2009 15:14:51 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/50#comment-284</link>
      <guid isPermaLink='false'>urn:uuid:6946c1de-2135-4cbc-8ecc-1814cd0e3c5e</guid>
    </item>
    <item>
      <title>"Using Postgresql with Grails" by Chris</title>
      <description>
        Wow - this is awesome. So, my main question is: how did you know to do this? I'm new to Java, and wouldn't even know where to start to do this myself. Do you have previous Hibernate experience, or were you just having an exceptionally clever day when you came up with this?
        
        Thanks tons for posting this. :)
      </description>
      <pubDate>Mon, 23 Nov 2009 10:06:48 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/50#comment-287</link>
      <guid isPermaLink='false'>urn:uuid:93a38ae4-9c88-429c-a5c8-cd7b773bf7fc</guid>
    </item>
    <item>
      <title>"Using Postgresql with Grails" by wolfman</title>
      <description>
        @Chris - I just started using Grails/Gorm/Hibernate, but I have been using JDBC and Spring for quite a while. I knew about the problem with Postgresql for a while, and have incorporated the RETURNING id in all my Spring DAOs for a while. I just Googled my ass off to find out how to do it for Hibernate, as I could not believe it was simply broken and unfixable. 
        
        I have to say that it probably took me 4 hours to track down the information on how to do it, and about 10 minutes to actually implement it.
      </description>
      <pubDate>Mon, 23 Nov 2009 14:59:19 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/50#comment-288</link>
      <guid isPermaLink='false'>urn:uuid:ad90c049-677c-46f9-b666-35e5726adcea</guid>
    </item>
    <item>
      <title>"Using Postgresql with Grails" by Chris</title>
      <description>@wolfman - thanks! I like Grails, but I'm always feeling like I'm missing something by not having Spring/Hibernate experience to start. LOL - that's the story of writing code, isn't it? Spending 90% of the time to figure out the solution, and 10% on the implementation. :)</description>
      <pubDate>Tue, 24 Nov 2009 10:06:55 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/50#comment-289</link>
      <guid isPermaLink='false'>urn:uuid:377a6b68-26c9-4809-a7a3-c13e002d35cc</guid>
    </item>
  </channel>
</rss>
