views:

429

answers:

3

Take the situation listed in this question:

http://stackoverflow.com/questions/261407/mapping-multi-level-inheritance-in-hibernate/1883829

How would this mapping be done with Annotations rather than an hbm file?

A: 

Inheritance between @Entity annotated classes is picked up automatically. So if you class A is annotated and class B is also annotated with @Entity and extends A, and C extends B and is also @Entity annotated all will be picked up.

I have not used joined subclasses combined with discriminator values, but I'm sure it will be very similar to what is done in XML (using @DiscriminatorColumn and @DiscriminatorValue)

Fried Hoeben
This is incorrect. There is a big difference between implicit polymorphism you're alluding to and actually mapping class hierarchy.
ChssPly76
Can you elaborate on this statement? I was not aware I was alluding to implicit polymorphism, not was I intending to. I wanted to describe a hierarchy A <- B <- C...
Fried Hoeben
"Inheritance between @Entity annotated classes is picked up automatically" - that's implicit polymorphism. In order to map the actual class hierarchy you have to explicitly annotated the root class with `@Inheritance` (plus use additional annotations depending on chosen strategy).
ChssPly76
A: 

The answer is here and it seems pretty clear, it's not possible using annotations.

Michal Bachman
This is, of course, incorrect. The (rather old) post you've linked to tries to use discriminators for joined subclass strategy (presumably in hopes of achieving better performance); _that_ is not supported out of the box but can be easily faked with table-per-hierarchy and joined tables. Mapping regular joined-subclass hierarchy is very much possible.
ChssPly76
+1  A: 

What specifically are you having trouble with? Mapping class hierarchy via joined subclasses is pretty straightforward:

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class A implements Serializable { ... }

@Entity
public class B extends A { ... }

@Entity
@PrimaryKeyJoinColumn(name="A_ID")
public class C extends A { ... }

@Entity
@PrimaryKeyJoinColumn(name="B_ID")
public class D extends B { ... }


Update (based on Michal's comment).

In case you do want to use discriminators (and you should have a good reason to do so), it's possible to do so by mixing table-per-class-hierarchy strategy with secondary tables:

@Entity
@Table(name="A_table")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="entity_type")
@DiscriminatorValue("A")
public class A implements Serializable { ... }

@Entity
@SecondaryTable(name="B_table")
public class B extends A { ... }

@Entity
@SecondaryTable(name="C_table", pkJoinColumns={
    @PrimaryKeyJoinColumn(name="A_ID", referencedColumnName="ID")
))
public class C extends A { ... }

@Entity
@SecondaryTable(name="D_table", pkJoinColumns={
    @PrimaryKeyJoinColumn(name="B_ID", referencedColumnName="ID")
))
public class D extends B { ... }

The downside to this approach is you'll have to explicitly specify the table for each property mapped:

public class D extends B {
  @Column(table="D_table")
  private String someProperty;

  ...
}
ChssPly76
I think this wasn't the question. He wants to use discriminator columns as far as I understood it. That's the reason for my answer buy you're reputation here is much higher, so I might very well be wrong :-)
Michal Bachman
@Michal - OP doesn't mention discriminator anywhere. Question he linked to says discriminator is used for historic reasons but doesn't say that he wants to keep using them. At any rate, if OP does want to use discriminators it's easily possible - I've updated my answer to show an example.
ChssPly76
Turns out I was on the right track but had a more basic issue in my hbm that caused my annotations to not be picked up. Thanks for the clear answer anyhow. Cheers!
evan.leonard
One question though, why do you say "you should have a *good* reason" to use discriminators? Our app has more than one usage of mapping classes to a single table using discriminators. Seems to be working very well. What is the drawback you're alluding to?
evan.leonard
Using table-per-hierarchy strategy is fine; the drawback is having multiple nulls in each row (and the inability to have not-null constraints on non-root classes). Using table-per-concrete-class strategy is fine too; the drawback is joins. When you combine the two you get the worst of both worlds and there's rarely a reason to do it this way.
ChssPly76