Grailsでテーブル毎にシーケンスを自動生成する方法
むかしJIRAにもチケット上がっていたみたいですが、
http://jira.grails.org/browse/GRAILS-3138
GrailsとうかHibernateの問題なのでcloseされた模様。
ということで、GrailsというよりHibernateの話ではあるのですがPostgreSQLDialectなど、getNativeIdentifierGeneratorClassにデフォルトのSequenceGeneratorが使用されている場合
... public Class getNativeIdentifierGeneratorClass() { return SequenceGenerator.class; } ...
というような実装になっており、とくにマッピングの指定など行わないと全テーブル共通でidの採番がhibernate_sequenceから行われてしまいます(嬉しいことないよね?)。
これをテーブル毎にシーケンスが作成されるようにしたいということでカスタムのDialectとSequenceGeneratorを作成します。こんなん(groovyで書いています)。
class MyDialect extends PostgreSQLDialect { @Override Class<?> getNativeIdentifierGeneratorClass() { TableNameSequenceGenerator.class } static class TableNameSequenceGenerator extends SequenceGenerator { @Override void configure(Type type, Properties params, Dialect dialect) { if (!params.getProperty(SEQUENCE)) { String tableName = params.getProperty(PersistentIdentifierGenerator.TABLE) if (tableName) { params.setProperty(SEQUENCE, "${tableName}_id_seq") } } super.configure(type, params, dialect) } } }
こいつをDataSource.groovyのdialectに自分が作ったMyDialectを差し替えればおk。
dataSource { driverClassName = "org.postgresql.Driver" dialect = org.yamkazu.portgresql.MyDialect dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', '' url = "jdbc:postgresql:grails" username = "grails" password = "grails" }
bookとauthorというドメインの場合以下の様な感じで、author_id_seq、book_id_seqが生成されます。
grails=# \ds List of relations Schema | Name | Type | Owner --------+---------------+----------+-------- public | author_id_seq | sequence | grails public | book_id_seq | sequence | grails (2 rows)
2012/07/13修正 DataSource.groovyの追記方法とシーケンス名の指定を少し修正しました