Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling an association with an interface using ORM in Java

I want to whether it's possible to handle an association with an abstract Entity (i.e: an Interface), in another Entity. e.g:
I have a class called Foo which has an attribute bar, which is of type Bar, which is an interface. Multiple classes (Bar1, Bar2) realize Bar and are all also persistable.

class Foo{
  Bar bar; // this will be either Bar1 or Bar2
}

interface Bar{ 
  // some methods
}

class Bar1 implements Bar{
  String s; // Bar1 and Bar2 have different represantations ,hence they must be persisted to different tables
}

class Bar2 implements Bar{
  int i;
}

Now how can I handle this with an ORM in Java? i.e: so that when I retrieve a Foo, it's bar is an instance of one of the realizations of Bar.

like image 273
user2268997 Avatar asked Jun 30 '16 07:06

user2268997


2 Answers

Yes, you can support polymorphic associations, but you'll need to make Bar an abstract base @Entity class instead of an interface, as JPA doesn't work well with interfaces, e.g.:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Bar {
    ...
}

@Entity
public class Bar1 extends Bar {
    private String s;
    ...
}

@Entity
public class Bar2 extends Bar {
    private int i;
    ...
}

If you model it this way, you'll be able to query for Bar instances polymorphically using JP-QL, e.g. select b from Bar.

Reference:

https://docs.oracle.com/javaee/7/tutorial/persistence-intro002.htm#BNBQN

like image 181
ck1 Avatar answered Oct 20 '22 04:10

ck1


Related to ck1's answer, but with a single table.

Using InheritanceType.JOINED requires a table for the base class, and one table per subclass. If you use InheritanceType.SINGLE_TABLE with a DiscriminatorColumn you can store all of your entities in a single table and still retrieve in a single collection. You can also combine the DiscriminatorColumn with InheritanceType.JOINED if you want to be able to tell what type of object is in the base class, while keeping the subclass specific fields in separate tables.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISC")
public abstract class Bar {
    ...
}

@Entity
@DiscriminatorValue("BAR1")
public class Bar1 extends Bar {
    ...
}

@Entity
@DiscriminatorValue("BAR2")
public class Bar2 extends Bar {
    ...
}
like image 20
JudgingNotJudging Avatar answered Oct 20 '22 03:10

JudgingNotJudging