Hibernate component (value object) inheritance mapping

25 Sep, 2007

Entity inheritance mapping in Hibernate can easily be done by following one of the three strategies and many a times instance of which subclass has to be created is identified by the value of the discriminator column (particularly in the case of table per class hierarchy). For such mappings there is already an inherent support in Hibernate.
So this is good if we want to create a sub class of a specific type for each row but what about if we want to create an instance of a specific class for a value of a column within that row. So in a way some type of component inheritance mapping. This is required if I really do not want to convert a value object (component) into an entity as that might mean sacrifice on the part of good model design as I am loosing the distinction between a component and an entity.
A workaround for the moment could be to somehow use a UserType to create instance of such objects based upon the value stored in the column. The concept of discriminator column can still help us. Let’s see how by taking up the following example

Suppose we have a catalog of books where each book has a price specification depending upon the currency of where the book was originally published. Each price specification is modeled by a separate class which has a property amount. Assume here that these classes have a different behavior depending upon the currency for calculation of sales tax and stuff (otherwise we can simply create a class and do the mapping using component or one-to-one).
So the book table looks something like this

And book class like this
[java]public class Book {
private long id;
private PriceSpecification priceSpecification;

And one of the price specifications may be
[java]public class USDollarSpecification implement PriceSpecification {
private long amount;
public void setAmount(long amount) {
this.amount = amount;
public long getMaximumRetailPrice() {

Now this can be obviously mapped using a UserType but to make it much cleaner lets use an Enum. Some sample code of PriceSpecificationUserType looks something like this.
[java]public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
String type = rs.getString(names[0]);
long amount = rs.getLong(names[1]);
PriceSpecificationType priceSpecType = priceSpecificationType.valueOf(type);
PriceSpecification specification = priceSpecType.getNewInstance();
return specification;
Here we create an instance of a price specification from the value in PRICE_SPEC_TYPE column using an Enum for price specification types.
[java]public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) throws HibernateException, SQLException {
if (value == null) {
preparedStatement.setNull(index, Types.VARCHAR);
preparedStatement.setNull(index + 1, Types.NUMERIC);
} else {
PriceSpecification priceSpecification = (PriceSpecification) value;
String className = priceSpecification.getClass().getName();
PriceSpecificationType[] priceSpecTypes = PriceSpecificationType.values();
for (int i = 0; i < priceSpecTypes.length; i++) {
PriceSpecificationType priceSpecType = priceSpecTypes[i];
if (priceSpecType.getClassName().equals(className)) {
preparedStatement.setInt(index + 1, priceSpecification.getAmount());
And similarly we set the price specification in PRICE_SPEC_TYPE using the Enum for price specification types.
Here is how Enum looks like
[java]public enum PriceSpecificationType {
public String getClassName() {
return USDollarSpecification.class.getName();
public PriceSpecification getNewInstance() {
return new USDollarSpecification();

public abstract PriceSpecification getNewInstance();
public abstract String getClassName();
And finally let’s see the mapping for this
<class name=”Book” table=”BOOK”

Hibernate might add a support for this in one of the future releases going by this but for now this might be a workaround we have to live with

Newest Most Voted
Inline Feedbacks
View all comments
14 years ago

I see the point you are trying to make, however the example is a bit strange, why would you want to persist a specification? Can’t you just initialize them when you wake up the object? Also maybe override the method isMutable? Value objects cannot be altered.

Maarten Winkels
14 years ago

Hi Priyanshu,
Very interesting blog! I\’m familiar with this approach and the one thing that annoys me is how intimatily the UserType needs to know about the class that it (de)serializes. It needs to know its public Constructor and its property names. This cannot be set in the configuration, as we are used to with entities and simple components in Hibernate.
Hibernate is very well able to work with conversion, handle nulls and set values to properties of objects. Actually, that\’s what the entire framework is for! I\’ve looked into the ComponentType to try and extend it to add this functionality, but the instantiate method is not passed the ResultSet, so it cannot query the row that is being created. This is the main reason why it\’s so hard to fix this more elegantly.
One more thing: By extending the CompositeUserType you could also query on properties of this component, like \”from Book where priceSpecification.amount = 12\”.
Cheers, Maarten Winkels

Gerrie Kimpen
Gerrie Kimpen
14 years ago

Hi Priyanshu,
Tnx for sharing this nice workaround.
Hopefully Hibernate will some day support component hierarchies since I would like to map component subclasses that each have their own set of properties … Unless I’m mistaken this is impossible to do, even with the help of your workaround, since you can only specify one set of columns in the priceSpecification mapping.
Let’s all vote

Explore related posts