Thursday, September 01, 2005

Hibernate inheritance mapping with hsqldb

Hibernate supports three inheritance mapping strategies:
  • table per class hierarchy
  • table per subclass
  • table per concrete class
The first two are pretty straightforward. Basically the first strategy maps the whole class hierarchy into one table, and classes are differentiated by a discriminator column. The second strategy maps the base class into one table, and additional attributes in subclasses are mapped to additional tables joined back to the base table with foreign keys. These two strategies can be combined together, and they are probably the most used in practice.

The third strategy is a little bit trickier. Each concrete class gets its own table, and all the inherited attributes are mapped to that table as well. The tricky part is you cannot use identity database type as the primary key, only sequence is allowed. The reason for this is that all the tables are unioned together so the primary keys have to be shared between the tables.

HSQLDB is a light-weight pure-java database that can be run in-memory and very useful for unit testing. It actually supports sequences, in addition to the identity type. If you specify "native" as the primary key generator, hibernate assumes you are using identity, and the third strategy would fail. So you have to specify "sequence" as the generator:

<id name="id" type="long" column="PAYMENT_ID">
<generator class="sequence" name="my_sequence">
</id>
In addition, when you create the hsqldb tables, you also need to create the sequence:

create table dual_my_sequence (zero integer);
insert into dual_my_sequence values (0);
create sequence my_sequence start with 1;

Since hsqldb lacks the equivenlant of a DUAL table in oracle, you have to create an associated table with one row to select on the sequence:

select my_sequence next value from dual_my_sequence;

There you have it how to configure table per concrete class in hsqldb.