[Grails] SEQUENCE generator name
Если у доменного объекта не указан способ генерации айдишника тогда Hibernate подбирает его сам. Это называется native стратегия.
Если вы используете не уродскую MySQL, а настоящую базу данных типа PostgreSQL, Oracle или Firebird, то генерация айдишников будет происходить через SEQUENCE.
При генерации БД название для сиквенсов генерируется автоматически и выглядят они примерно так: SYSTEM_SEQUENCE_99A7416D_98E6_485C_8568_1DD6C99BF31C
. Т.е. нейминг стратегия мягко говоря неадекватная.
Из-за неё возникает несколько проблем.
Во первых из названия такого сиквенса не понятно для какой именно он таблицы.
Во вторых, я сталкивался с проблемой когда при следующем релизе через database migration накатываются изменения и возникает необходимость сбросить сиквенс, то не ясно по какому имени к нему обращаться.
Как решать?
Переопределить нейминг
Первый вариант создать свой диалект внутри которого прописать правильную генерацию имени сиквенса.
По уму стоило бы всё таки пропатчить эту паскудную генерацию имени сиквенсов в самом хибернейте. Ставлю пивашку тому кто это сделает 🙂
Указать имя сиквенса явно
Для того чтобы обойти эту проблему можно в мапинге домена явно указать имя сиквенса:
class Book { String title static mapping = { id generator: 'sequence', params: [sequence: 'book_seq'] } }
Теперь для таблицы book
будет создан сиквенс book_seq
.
Естественно, если вы вдруг решите запустить приложение на БД в которой нет сикенсов то отгребёте ошибку типа такой org.hibernate.MappingException: org.hibernate.dialect.MySQL5InnoDBDialect does not support sequences
.
Так что такое решение не годится для использования если вам не известная используемая БД, например в плагинах.
Правильное решение
Я сначала подумал что на этом тупик, но пролистав документацию хибернейта дальше обнаружил что решение уже есть.
Если вкратце, то начиная с версии 3.2.3 в хибернейте появился SequenceStyleGenerator
который в отличии от нейтив, позволяет указать опции одновременно и для SEQUENCE генератора и для Table не падает с ошибкой на старте.
class Book { String title static mapping = { id generator: 'org.hibernate.id.enhanced.SequenceStyleGenerator', params: [sequence_name: 'book_seq'] } }
В документации сказано что ещё следует включить новые генераторы. Для этого в DataSource.groovy
нужно добавить опцию
hibernate.id.new_generator_mappings = true
Но если честно, то всё и без этого заработало 🙂
Теперь в MySql рядом с таблицей book
создалась таблица book_seq
с одной строкой и одним полем next_val
которая имитирует сиквенс.