dstarh
dstarh

Reputation: 5076

How does hibernate know which subclass to create when using Joined inheritence

if I have

@Inheritance(strategy = InheritanceType.JOINED)
Organization{
}

Account extends Organization{
   private Organization organization
}

Client extends Organization{
   private Organization organization
}

User {
   private Organization organization
}

When I call userDAO.get(1) and get back an instance of User, how does hibernate know to give me back an instance of Account rather than Client?

Upvotes: 1

Views: 1197

Answers (3)

stefan
stefan

Reputation: 1569

NOTE: Applies to SINGLE_TABLE strategy only, see @Tomazs' response for JOINED strategy.

Hibernate stores the explicit subclass used as some form of enumeration, generally as a string value, in the database. You can set the name of this column using the @DescriminatorColumn annotation, and then use the @DiscriminatorValue annotation on subclasses. When Hibernate goes to store an Account in the database, any rows which are specific to say, Client, are still stored for that Account but are set to null, and the DiscriminatorColumn is set to "Account". Then, when the organization is deserialized, Hibernate looks at that DiscriminatorColumn, sees that the Organization is an Account, and gives you back that type of object.

The DescriminatorColumn can be changed to use other types of data, eg. not strings, using the columnDefinition parameter. By default the name of this column is DTYPE, and values for classes which do not have a DiscriminatorValue are the name of the class.

Upvotes: 0

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340753

Without discriminator

Hibernate performs an OUTER JOIN with every child table:

SELECT *,
case
    when a.id is not null then 0
    when c.id is not null then 1
    when u.id is not null then 2
end as clazz
FROM Organization o
    OUTER JOIN Account a
    OUTER JOIN Client c
    OUTER JOIN User u

And determines the actual type by looking at which OUTER JOIN actually returned something. Obviously there will be exactly one table from Account, Client and User holding a record that has the same id - and this denotes the actual type. This is what the awkward case/when does.

With discriminator

If the discriminator column is present, OUTER JOINs are still needed, but it is easier to determine the actual type, as it is explicitly stored in the database. No case/when magic.

Summary

As you can see this inheritance strategy is very inefficient. It is much better when you explicitly ask for a given subtype, because Hibernate will do an JOIN with only a single table.

See also:

Upvotes: 2

Bozho
Bozho

Reputation: 597114

For each record hibernate can store an additional (discriminator) column in the main table that indicates which type is used.

Upvotes: 1

Related Questions