Hibernate: Is it possible to map multi-level inheritance to single table?
Asked Answered
S

3

10

I have following inheritance hierarchy:

Task
  |
SpecificTask
  |
VerySpecificTask

And I'd like to persist it usign single-table inheritance, so I annotated classes:

@Entity
@Table(name="task")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Task 

@Entity
public class SpecificTask extends Task 

@Entity
public class VerySpecificTask extends SpecificTask

When I try to save an object of VerySpecificTask class, I get an error:

Unable to resolve entity name from Class [com.application.task.VerySpecificTask] 
expected instance/subclass of [com.application.task.Task]

What do I wrong? Is it possible to map multi-level inheritance to single table?

EDIT: Here was a lame bug, I've resolved quickly, so I deleted it to not mess this question.

Scyphozoan answered 3/2, 2012 at 15:6 Comment(4)
Have you configured a discriminator column? What's the stack trace of the exception?Merman
I use appFuse and disctiminator is set automagically.Scyphozoan
Multi level inheritance is allowed by JSR 303. Are you sure appFuse is applying annotations past the first level in the inheritance tree?Bedraggled
I would definitely make sure all that automagic stuff is working as you think and set up correctly. If this had discriminator columns, it should work.Iminourea
S
6

OK, I've added discriminator column and now it works. Changed code:

@Entity
@Table(name="task")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name="DTYPE",
        discriminatorType=DiscriminatorType.STRING
    )

@Entity
public class SpecificTask extends Task 

@Entity
public class VerySpecificTask extends SpecificTask

(I'm adding it just to provide an accepted answer -- I wouldn't resolve it without the helpful comments to the question.)

Scyphozoan answered 6/2, 2012 at 8:26 Comment(0)
K
3

The accepted answer is almost perfect. To make it more clear I want to add a @DiscriminatorValue to each inheritance level.

@Entity
@Table(name="task")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
        name="DTYPE",
        discriminatorType=DiscriminatorType.STRING
)
public class Task

---

@Entity
@DiscriminatorValue(value="DS")
public class SpecificTask extends Task 

---

@Entity
@DiscriminatorValue(value="DV")
public class VerySpecificTask extends SpecificTask

And the materiliazed table looks like

--------------- 
Table: task
---------------
|...|DTYPE|...|
---------------
|...|DS   |...|
|...|DV   |...|
|...|DS   |...|
...
Karlenekarlens answered 17/5, 2016 at 14:16 Comment(0)
R
0

Try the @MappedSuperclass annotation :

@MappedSuperclass
public class BaseEntity {
    @Basic
    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastUpdate() { ... }
    public String getLastUpdater() { ... }
    ...
}

@Entity 
public class Order extends BaseEntity {
    @Id public Integer getId() { ... }
    ...
}

In database, this hierarchy will be represented as an Order table having the id, lastUpdate and lastUpdater columns. The embedded superclass property mappings are copied into their entity subclasses. Remember that the embeddable superclass is not the root of the hierarchy though.

Rookery answered 3/2, 2012 at 15:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.