MichaelCleverly
MichaelCleverly

Reputation: 2543

Hibernate JPA Joined Inheritance

I have a project with a part of the data structure made with @Inheritance(strategy = InheritanceType.JOINED). That part of the data structure looks something like this:

enter image description here

The design is based on the thoughts in this article. I'm using Hibernate with JPA2 interface as my datalayer. The structure above has resulted in the following pojo/dao classes (getters and setter omitted):

BaseItem:

@Entity
@Table( name = "base_item" )
@Inheritance(strategy = InheritanceType.JOINED)
public class BaseItemPojo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
}

PhysicalItem:

@Entity
@Table( name = "physical_item" )
public class PhysicalItemPojo extends BaseItemPojo{
}

SomeHardware:

@Entity
@Table( name = "some_hardware" )
public class SomeHardwarePojo extends PhysicalItemPojo{
}

SomeOtherHardware:

@Entity
@Table( name = "some_other_hardware" )
public class SomeOtherHardwarePojo extends PhysicalItemPojo{
}

Here is my issue:

One of my other tables has a reference to the base_item class, and it would make my life a lot easier, if that class loaded either the "some_hardware" or the "some_other_hardware" based on that base_item_id. Hence, I made navigation properties like this on that particular class:

@Entity
@Table( name = "some_navigation_class" )
public class SomeNavigationClassPojo{
    @ManyToOne(optional = false)
    @JoinColumn(name="base_item_id", insertable = false, updatable = false)
    private BaseItemPojo baseItem;

    @ManyToOne
    @JoinColumn(name="base_item_id", insertable = false, updatable = false)
    private PhysicalItemPojo physicalItem;

    @ManyToOne()
    @JoinColumn(name = "base_item_id", insertable = false, updatable = false)
    private SomeHardwarePojo someHardwarePojo;

    @ManyToOne()
    @JoinColumn(name = "base_item_id", insertable = false, updatable = false)
    private SomeOtherHardwarePojo someOtherHardwarePojo;
}

As you might have guessed, the above didn't work. If I try to access a "SomeNavigationClassPojo" that has a related "SomeHardwarePojo" attached to the entity, I get the following error:

java.lang.IllegalArgumentException: Can not set SomeOtherHardwarePojo field SomeNavigationClass.someOtherHardware to SomeHardwarePojo.

For reference, my goal is that if either someHardwarePojo or someOtherHardwarePojo doesn't exist in the database, they should just be set to null, and not tried to be mapped to respective other child of PhysicalItemPojo

Upvotes: 1

Views: 598

Answers (1)

Tobias Liefke
Tobias Liefke

Reputation: 9032

You can add the attributes as simple getters:

public class SomeNavigationClassPojo {
    ...
    public SomeHardwarePojo getSomeHardwarePojo() { 
        return baseItem instanceof SomeHardwarePojo ? (SomeHardwarePojo) baseItem : null; 
    }
    ...
}

The major drawback: You can't use the attributes in a JPA query - e.g. something like SELECT n FROM SomeNavigationClassPojo n JOIN n.somehardwarepojo s WHERE s.propertyOfHardwarePojo = 'x' is not possible.

Upvotes: 0

Related Questions