3

I want to create a custom sequence generator in Hibernate 5 to create a sequence per table in Postgresql. Using Hibernate 4 I did the following in my dialect:

/**
 * Get the native identifier generator class.
 *
 * @return TableNameSequenceGenerator.
 */
@Override
Class<?> getNativeIdentifierGeneratorClass() {
    TableNameSequenceGenerator
}

/**
 * Creates a sequence per table instead of the default behavior of one sequence.
 * From <a href='http://www.hibernate.org/296.html'>http://www.hibernate.org/296.html</a>
 */
static class TableNameSequenceGenerator extends SequenceGenerator {

    /**
     * {@inheritDoc}
     * If the parameters do not contain a {@link SequenceGenerator#SEQUENCE} name, we
     * assign one based on the table name.
     */
    @Override
    void configure(final Type type, final Properties params, final Dialect dialect) {

        Boolean sequencePerTable = Holders.config.getProperty(SEQUENCE_PER_TABLE, Boolean, true)

        if (sequencePerTable) {
            if (!params.getProperty(SEQUENCE)) {
                String tableName = params.getProperty(TABLE)
                String schemaName = params.getProperty('schemaName')
                if (schemaName) {
                    params.setProperty(SCHEMA, schemaName)
                }
                if (tableName) {
                    params.setProperty(SEQUENCE, "seq_${tableName}")
                }
            }
        }
        super.configure(type, params, dialect)
    }
}

You can see the full code here: https://github.com/kaleidos/grails-postgresql-extensions/blob/master/src/main/groovy/net/kaleidos/hibernate/PostgresqlExtensionsDialect.groovy#L53

I'm trying to migrate to Hibernate 5 but I don't know how to configure the previous behavior. I've modified the code to extends from SequenceStyleGenerator because now SequenceGenerator has been deprecated but my code is never executed. I think this has to do with the fact that the method getNativeIdentifierGeneratorClass has also been deprecated.

I've been looking for a way to create a custom sequence but all examples I've found are focused on annotate my domain class with the sequence generator. What I'm looking for is a way to define all the sequences in a global way.

Iván López
  • 944
  • 4
  • 13
  • `spring.jpa.hibernate.use-new-id-generator-mappings: true` config is required in `application.yml` in order to use `SequenceStyleGenerator` – dmahapatro Nov 03 '16 at 16:12
  • On a side note, `getNativeIdentifierGeneratorClass()` can be replace by `getNativeIdentifierGeneratorStrategy()` which return a `String` – dmahapatro Nov 03 '16 at 16:18
  • `use-new-id-generator-mappings` might not work in a Grails app because that is specific to spring data jpa. – dmahapatro Nov 03 '16 at 16:35

2 Answers2

3

As Graeme noted (https://github.com/grails/grails-core/issues/10234) the default name of the sequence has changed in Hibernate 5, so adding

id generator: 'sequence', params: [sequence_name: 'book_seq']

to the mapping block does the trick. The problem is that it's necessary to add that to every domain class.

I'm still looking for a way to define that setting globally, maybe setting prefer_sequence_per_entity to true for every entity.

UPDATE: Finally we found a workaround to define a sequence per table globally. Just add the following to the file application.groovy:

grails.gorm.default.mapping = {
    id generator: 'org.hibernate.id.enhanced.SequenceStyleGenerator', params: [prefer_sequence_per_entity: true]
}
Iván López
  • 944
  • 4
  • 13
1

Thanks a lot Ivan! I tried only this configuration, which worked too.

 grails.gorm.default.mapping = {
      id  params: [prefer_sequence_per_entity: true]
 }
Amit Jain
  • 1,372
  • 8
  • 16