Updates for “Delayed SessionFactory Creation in Grails”
Back in the beginning of 2010 I did a post on how to delay creating the SessionFactory based on a discussion on the User mailing list. This has come up again
and I thought I’d look and see if things had changed for Grails 2.
The general problem is the same as it was; Grails and Hibernate create database connections during startup to help with configuration, so the information that is auto-discovered has to be explicitly specified. In addition any eager initialization that can wait should wait.
One such configuration item is the lobHandlerDetector
bean. This hasn’t changed from before, so the approach involves specifying the bean yourself (and it’s different depending on whether you’re using Oracle or another database). Since it’s the same I won’t include the details here; see the previous post.
Another is the Dialect
. Again, this is the same as before – just specify it in DataSource.groovy
. This is a good idea in general since there might be particular features you need in a non-default Dialect
class, and specifying org.hibernate.dialect.MySQL5InnoDBDialect
for MySQL guarantees that you’ll be using transactional InnoDB tables instead of non-transactional MyISAM tables.
The remaining issues have to do with eager initialization. I started down the path of reworking how to lazily initialize the SessionFactory
since using a Spring bean post-processor is significantly less involved (and brittle) than the approach I had previously used. But it turns out that the more recent version of Hibernate that we’re now using supports a flag that avoids database access during SessionFactory
initialization, hibernate.temp.use_jdbc_metadata_defaults
. So add this to the hibernate
block in DataSource.groovy:
hibernate { ... temp.use_jdbc_metadata_defaults = false }
And the last issue is the DataSource
itself. Up to this point all of the changes will avoid getting a connection, but the pool might pre-create connections at startup. The default implementation in Grails is org.apache.commons.dbcp.BasicDataSource
and its initial size is 0, so you’re ok if you haven’t configured a different implementation. If you have, be sure to set its initial size to 0 (this isn’t part of the DataSource
so the setter method is implementation-specific if it even exists).
If you’re using multiple datasources, you can delay their database connectivity too. There is a lobHandlerDetector
bean for each datasource, so for example if you have a second one with the name “ds2”, configure a lobHandlerDetector_ds2
bean in resources.groovy. Likewise for the Dialect
; specify it in the dataSource_ds2
block in DataSource.groovy. Set the use_jdbc_metadata_defaults
option in the hibernate_ds2
block:
hibernate_ds2 { ... temp.use_jdbc_metadata_defaults = false }
And finally, as for the single-datasource case, if you’ve reconfigured secondary datasource beans’ pool implementations, set their initial sizes to 0.
That was very useful! Thanks for sharing!
[…] there’s a Burt’s post that explains how to delay this […]