mrzasa
mrzasa

Reputation: 23327

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

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.

Upvotes: 10

Views: 5446

Answers (3)

Paul Wasilewski
Paul Wasilewski

Reputation: 10372

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   |...|
...

Upvotes: 3

mrzasa
mrzasa

Reputation: 23327

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.)

Upvotes: 6

Jean Logeart
Jean Logeart

Reputation: 53829

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.

Upvotes: 0

Related Questions