tags:

views:

190

answers:

2

I have a Hibernate hbm.xml mapping file which defines a large number of class mappings. Each of these needs an <id> definition and a corresponding <generator> definition.

In this particular application, the <generator> definition is quite involved, including setting a number of parameters (e.g. increment size, optimizer, etc). Having to repeat this definition for every class is tedious and clutters up the mapping.

If I were using JPA annotations, I could define the ID generator at the package level. But I'm not using JPA (nor is it an option), and it seems most peculiar to be able to do something in JPA but not native hibernate.

Can I specify the generator elsewhere, and refer to it multiple times in the mapping?

+1  A: 

A workaround would be to define it in a template XML and then use a small XML program or an XSLT script to build the mapping files.

That would also allow you to reuse definitions of other things (like complex column mappings).

Aaron Digulla
+1  A: 

This is sadly one of very few things Hibernate Annotations supports but Hibernate Core does not. The way I've worked around this issue in the past was to:

  1. Write my own IdentifierGenerator implementation; make it implement Configurable as well.
  2. Have it hold a static map of generator properties keyed by unique name (each map entry will represent a "predefined" generator configuration).
  3. Said configurations are declared as beans in Spring context using this very same class (or , if you want / need some type safety you can make them actual beans with setters). Post-creation callback (e.g. afterPropertiesSet()) adds bean properties to the above map using bean id as key. The underlying generator "strategy" is one of those properties.
  4. Configurable.configure() grabs the underlying generator via IdentifierGeneratorFactory.getIdentifierGeneratorClass() and initializes it with Properties instance passed to configure() merged with properties retrieved from the above map.

So, in Hibernate mappings you'd do something like:

<generator class="com.mypackage.PredefinedGenerator">
  <param name="preset">preset1</param>
</generator>

In your Spring context:

<bean id="preset1" class="com.mypackage.PredefinedGenerator">
  <property name="parameters"><props>
    <prop key="generatorStrategy">seqhilo</prop>
    <prop key="sequence">my_sequence</prop>
    <prop key="max_lo">500</prop>
  </props></property>
</bean>

This can be simplified, of course, if you don't need multiple presets. I can't post the actual code for legal reasons; but if you're interested in this approach but the above isn't clear please comment and I'll try to clarify.

ChssPly76
That's quite inventive :)
skaffman