Reputation: 977
I have a problem with JPA inheritance. See my entities below. I have a Person
that can be in either a House
or a Car
, never at the same time of course. Both Car
and House
implement the PersonHoldable
interface. I know I cannot map an Entity directly to an interface.
This is my model:
@Entity
public class Person{
private PersonHoldable personHoldable; // either a Car or a House
// This does not work of course because it's an interface
// This would be the way to link objects without taking JPA into consideration.
@OneToOne
public PersonHoldable getPersonHoldable() {
return this.personHoldable;
}
public void setPersonHoldable(PersonHoldable personHoldable) {
this.personHoldable = personHoldable;
}
}
@Entity
public class Car implements PersonHoldable{}
@Entity
public class House implements PersonHoldable{}
public interface PersonHoldable{}
How can I map this correctly in JPA taking the following into consideration?
@MappedSuperclass
on an abstract implementation of PersonHoldable
. Although it will work for this particular setup, the problem with this is that Car
and House
in reality implement more interfaces. And they are mapped to other entities as well.Person
could have a property for every possible PersonHoldable
, so in this case it could have a getCar()
and getHouse()
property. That does not seem very flexible to me. If I would add a Bike
implementation of the PersonHoldable
I would have to change my Person
class.PersonHoldable
implementation side. This would mean adding a getPerson()
property to the PersonHoldable
. But then it's not very easy from a Person
perspective to see what PersonHoldable
it is linked to.If this is not possible with default JPA, what would be best practice in this case?
Upvotes: 0
Views: 523
Reputation: 3707
A slight variation on your second point would be to make Person have an inheritance type and implement a CarPerson and HousePerson (and later a BikePerson) whose whole purpose is to define the specific join relationship to a specific PersonHolder implementation. That keeps the relationship intact and more easily queryable from the Person side.
@Inheritance(strategy = JOINED)
@DiscriminatorColumn(name="holdableType", discriminatorType=CHAR, length=1)
@Entity
public class Person {
// common fields
}
@Entity
@DiscriminatorValue("C")
public class CarPerson extends Person {
@OneToOne
private Car car;
}
@Entity
@DiscriminatorValue("H")
public class HousePerson extends Person {
@OneToOne
private House house;
}
Upvotes: 1