Iván López Iván López - 1 month ago 24
Java Question

Custom sequence generator for Hibernate 5

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.

Answer

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]
}