3

Fellow developers, I'm finding it hard to get the sequence generation configured.

I inherited a persistent class with the following id field definition:

@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;

All of my classes inherit from this class.

The main thing I want: I need to override the strategy of id generation to use HiLo. It has to be in the cfg.xml since it's the only place that I have control over.

This thing looked promising:

<property name="hibernate.id.new_generator_mappings">true</property>

However I couldn't choose the optimize, or the increment size (I want to go HiLo)

<property name="hibernate.id.increment_size">50</property>
<property name="hibernate.id.optimizer">hilo</property>

didn't work, nor

<property name="increment_size">50</property>
<property name="optimizer">hilo</property>

nor

<property name="optimizer">org.hibernate.id.enhanced.HiLoOptimizer</property>

The NoopOptimizer is always chosen.

Any tip will help. Thanks a lot in advance.

Eyad Ebrahim
  • 971
  • 1
  • 8
  • 21
  • Do you have some additional applicationContext.xml file that might overwrite your settings in the cfg.xml? See also http://stackoverflow.com/a/12636086/2615437? – xwoker Nov 09 '13 at 17:26
  • Do you have debug level logging enabled for hibernate and does it say something about which properties you are using? – xwoker Nov 09 '13 at 19:05
  • I don't have such a file. I think the properties I'm using may not be the right ones. I will check the thing about which properties being used exactly. – Eyad Ebrahim Nov 10 '13 at 21:47

2 Answers2

2

Let's do some investigation (looking at the Hibernate sources):

The AnnotationBinder defines how AUTO is mapped:

switch ( generatorEnum ) {
  // ...
  case AUTO:
    return useNewGeneratorMappings ? 
      org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName() : "native";
  // ...

If you don't use the NewGeneratorMappings you're stuck with the native implementation. Hibernate will resolve that depending on the database (see this answer to see what that will be for your specific database).

But since you used the NewGeneratorMappings we have to look at the SequenceStyleGenerator:

protected String determineOptimizationStrategy(Properties params, int incrementSize) {

  // ... some stuff to calculate defaultOptimizerStrategy

  // OPT_PARAM = "optimizer"
  return ConfigurationHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy);
}

Assuming the right Properties are passed and you have an "optimizer" property in them then your value should be returned. This value is used to call OptimizerFactory.buildOptimizer (as the first parameter):

 public static Optimizer buildOptimizer(String type, Class returnClass, int incrementSize) {
   final Class<? extends Optimizer> optimizerClass;

   final StandardOptimizerDescriptor standardDescriptor = 
     StandardOptimizerDescriptor.fromExternalName( type ); // HILO("hilo", HiLoOptimizer.class),
   if ( standardDescriptor != null ) {
     optimizerClass = standardDescriptor.getOptimizerClass();
   }
   else {
     try {
       optimizerClass = ReflectHelper.classForName( type );
     }
   catch( Throwable ignore ) {
     LOG.unableToLocateCustomOptimizerClass( type );
     return buildFallbackOptimizer( returnClass, incrementSize );
   }
 }

 try {
   final Constructor ctor = optimizerClass.getConstructor( CTOR_SIG );
   return (Optimizer) ctor.newInstance( returnClass, incrementSize );
 }
 catch( Throwable ignore ) {
   LOG.unableToInstantiateOptimizer( type );
 }

  return buildFallbackOptimizer( returnClass, incrementSize );
}

private static Optimizer buildFallbackOptimizer(Class returnClass, int incrementSize) {
  return new NoopOptimizer( returnClass, incrementSize );
}

So either it finds your value "hilo" (or your "HiLoOptimizer"), instantiates it and returns it or it will log some error message. If you find no error message in your logs I would check whether the properties in the cfg.xml are actually really used. Try to access them with getProperties() on your org.hibernate.internal.SessionFactoryImpl instance.

Community
  • 1
  • 1
xwoker
  • 3,105
  • 1
  • 30
  • 42
  • when I tried to debug this code, It showed that using the Auto method without having a generator will not actually go through this code exactly as I expected. The properties to build the optimizer from were only limited because "there was no generator" (it's in the annotation of the @ID). I don't remember the code section exactly, but I will get it another shot to check the getProperties. – Eyad Ebrahim Nov 10 '13 at 21:49
  • would you happen to know, where one can find a comprehensive list of all the configuration properties for hibernate.cfg.xml? Thanks by the way. – Eyad Ebrahim Nov 10 '13 at 21:49
  • No, not a comprehensive list. The Hibernate docs are not *that* complete… That's the reason why I would look try to see for which properties the relevant code is looking and see whether the actual used properties are really the ones from the cfg.xml – xwoker Nov 11 '13 at 14:56
  • I did lots of debugging and sadly the following will not work: // OPT_PARAM = "optimizer" return ConfigurationHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy); because params do not have OPT_PARAM inside in the properties even though it's in the SessionFactoryImpl.getProperties(). The params passed in the method is built on the fly and it does not have all the properties in the session factory. Another thing is, SessionFactoryImpl.getProparties() returns all the properties that are not defined by hibernate. so printing will not help – Eyad Ebrahim Nov 13 '13 at 16:16
0

So far there is no way to do this. but also I couldn't find a way to do this with the new

hibernate.id.new_generator_mappings = true

This one will use the new SequenceStyleGenerator but I couldn't configure this. The parameters used for configuration such as "optimizer" and "increment_size" are not passed to the method that configures the generator.

My point is, I do not know how this "hibernate.id.new_generator_mappings" is supposed to be used to make use of a hilo optimizer and configure properly and my reverse engineering capability proved unreliable.

To use hilo I had to do this @GeneratedValue(strategy = SEQUENCE) which works for testing but it's not a good option for me.

thanks @xwoker but i couldn't get it done.

Eyad Ebrahim
  • 971
  • 1
  • 8
  • 21