MappingException: Could not interpret id generator strategy with custom id generator

barclay picture barclay · Jan 23, 2014 · Viewed 8.4k times · Source

I need a custom id generator that saves the last used id rather than the next available, so based on this answer https://stackoverflow.com/a/10648572/187423 I created a custom generator extending TableGenerator.

I've determined in debug mode that my custom generator is not getting added to org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.generatorStrategyToClassNameMap, so it doesn't know how to interpret my generator. (It also seems that I should be using a handle rather than a class name, but again - not sure how to get this into the map.)

I'm also using Dropwizard, which complicates things. I'm not sure how or where I need to let DW know about my custom generator, but I've tried adding my class to the HibernateBundle, to the run() method in my DW service, to the injector, etc.

Here's where I use my generator in the class:

public class MexpFeedError {
    private int mexpFeedErrorId;

    @Id
    @GeneratedValue(strategy=GenerationType.TABLE, generator = "MEXPFEEDERROR_GEN")
    @GenericGenerator(name = "MEXPFEEDERROR_GEN", strategy = "com.pronto.util.ProntoPersistJustUsedGenerator",
            parameters = {
                    @org.hibernate.annotations.Parameter(name = "table_name", value = "sequence"),
                    @org.hibernate.annotations.Parameter(name = "segment_value", value = "seq_mexpfeederrorid"),
                    @org.hibernate.annotations.Parameter(name = "value_column_name", value = "sequence_value"),
                    @org.hibernate.annotations.Parameter(name = "segment_column_name", value = "sequence_name") })
    public int getMexpFeedErrorId() {
        return mexpFeedErrorId;
    }
    ...
}

Here's my custom generator:

package com.pronto.util.hibernate;

import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.enhanced.TableGenerator;

import java.io.Serializable;

@SuppressWarnings("UnusedDeclaration")
public class ProntoPersistJustUsedGenerator extends TableGenerator {

    @Override
    public synchronized Serializable generate(SessionImplementor session, Object obj) {
        return (Long) super.generate(session, obj) + 1;
    }
}

Here's the stack trace:

Exception in thread "main" org.hibernate.MappingException: Could not instantiate id generator [entity-name=com.pronto.mpds.entity.MexpFeedError]
    at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.createIdentifierGenerator(DefaultIdentifierGeneratorFactory.java:123)
    at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:195)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:314)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1769)
    at com.yammer.dropwizard.hibernate.SessionFactoryFactory.buildSessionFactory(SessionFactoryFactory.java:77)
    at com.yammer.dropwizard.hibernate.SessionFactoryFactory.build(SessionFactoryFactory.java:35)
    at com.yammer.dropwizard.hibernate.HibernateBundle.run(HibernateBundle.java:38)
    at com.yammer.dropwizard.hibernate.HibernateBundle.run(HibernateBundle.java:13)
    at com.yammer.dropwizard.config.Bootstrap.runWithBundles(Bootstrap.java:77)
    at com.yammer.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:37)
    at com.yammer.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:58)
    at com.yammer.dropwizard.cli.Cli.run(Cli.java:53)
    at com.yammer.dropwizard.Service.run(Service.java:61)
    at com.pronto.mpds.service.DropwizardMPDSService.main(DropwizardMPDSService.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.hibernate.MappingException: Could not interpret id generator strategy [com.pronto.util.ProntoSequenceStyleGenerator]
    at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.getIdentifierGeneratorClass(DefaultIdentifierGeneratorFactory.java:140)
    at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.createIdentifierGenerator(DefaultIdentifierGeneratorFactory.java:114)
    ... 18 more

Hope there's a wizard out there with some useful ideas for me. Thanks.

Answer

Mikko Maunu picture Mikko Maunu · Jan 24, 2014

ProntoPersistJustUsedGenerator is located to com.pronto.util.hibernate package, butcom.pronto.util package is used in GenericGenerator annotation.

Problem goes away when using full package name as a value of strategy attribute:

 strategy = "com.pronto.util.hibernate.ProntoPersistJustUsedGenerator"