7

I have 3 entities:

@Entity
public abstract class A {
  @Id
  public Long id;
  public String a1;
  public String a2;
  public String a3;

  //much more fields    
  //getters and setters
}

@Entity
public class B extends A {
  public String b1;
  public String b2;
  public String b3;

  //much more fields
  //getters and setters
}

@Entity
public class C extends A {
  public String c;
  //that's it. no more data

  //getters and setters
}

I want to map these classes to 2 tables. First one will contain all of A and C data (i.e. SINGLE_TABLE inheritance). And the second one will contain B's data and a foreign key to A (i.e. JOINED inheritance).

I tried the solution proposed here, but it doesn't work for me. The attributes of BB1 and BB2 are also included into A.

How to implement such a strategy? Classes A and C are as different as Dog and Cat are, so I can't merge them into one class.

Also I don't want to use table-per-hierarchy which would result in duplicating lots of A's data.

Community
  • 1
  • 1
jFrenetic
  • 5,384
  • 5
  • 42
  • 67
  • im not clear why you want to use a join strategy...the recommended way in the hibernate docs is to use table-per-class hierarchy with a discriminator -- will make your life simpler. perhaps put some details into those classes to help us understand? – hvgotcodes Oct 06 '11 at 20:43
  • @hvgotcodes Using TABLE_PER_CLASS strategy will lead to unnormalized data. Also, the inheritance tree could be quite large, so it would hurt performance as well. – jFrenetic Oct 06 '11 at 20:49
  • the tradeoff might be worth the unnormalized data. How large could the inheritance tree be, and how different are the classes in the hierarchy? – hvgotcodes Oct 06 '11 at 20:51
  • @hvgotcodes The inheritance tree could be about 5 levels deep. The thing here is that class `A` contains a lot of fields, so is the class `B`, but `C` has just one. So it looks really redundant to copy all fields of `A` twice. Our DBA definitely won't approve it. – jFrenetic Oct 06 '11 at 20:58
  • i said table per class *hierarchy*, not table per concrete subclass. one table for all the classes. – hvgotcodes Oct 06 '11 at 21:00
  • 2
    In my opinion you should try to convince your DBA that a consistent data model is more important than a small performance boost. If you already have a inheritance depth of 5 using the JOINED strategy then I would also use JOINED for C. – Jörn Horstmann Oct 13 '11 at 12:51
  • @JörnHorstmann Thanks for sharing your thoughts. I think so too, but sometimes it's not us who decide. The inheritance tree turned up being not so deep, and the top class is using SINGLE_TABLE hierarchy, however I used the trick which I described in my own answer to switch to another table. I've lost the benefits of inheritance but made it work eventually. – jFrenetic Oct 15 '11 at 19:25
  • Hibernate used to allow mixing inheritance, but I don´t know how to do it using pure JPA. Look here: https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/inheritance.html#inheritance-mixing-tableperclass-tablepersubclass – atorres Aug 02 '16 at 14:12

2 Answers2

6

JPA spec (paragraph 2.12) is saying that Support for the combination of inheritance strategies within a single entity inheritance hierarchy is not required by this specification. Keeping that in mind, in similar cases I usually use JOINED strategy for all of my entities.

andbi
  • 4,426
  • 5
  • 45
  • 70
1

After spending so much time on this, and not getting any answer, I've come to this solution (which could be not the best):

@Entity
public abstract class A implements Serializable {
  @Id
  public Long id;

  public String a1;
  public String a2;
  public String a3;

  //much more fields    
  //getters and setters
}

@Entity
public class B implements Serializable {

  @Id  
  @Column(name="id", nullable=false)  
  public Long id;

  @MapsId  
  @OneToOne(optional=false)  
  @JoinColumn(name="id")  
  public A a;

  public String b1;  
  public String b2;  
  public String b3;

  //much more fields
  //getters and setters
}

@Entity
public class C extends A {  

  public String c;
  //that's it. no more data

  //getters and setters
}

Conclusion
I was amazed at how such well-supported and popular technology as JPA does not offer a solution for such a trivial case. As pointed out by Pascal Thivent in his answer to this question, Hibernate is cheating us, using a secondary table, which is a very tedious and error-prone approach (you should manually specify for each field, to which table it belongs). So it looks like, there is still a room for improvement in JPA spec.

Community
  • 1
  • 1
jFrenetic
  • 5,384
  • 5
  • 42
  • 67
  • 1
    Current JPA spec (paragraph 2.1.10) is saying that `Support for the combination of inheritance strategies within a single entity inheritance hierarchy is not required by this specification.` Keeping that in mind, in similar cases I use JOINED strategy for all of my entities. – andbi Oct 16 '11 at 20:19
  • Thanks for pointing this out. Will hope that in the next version of spec, this feature will be mandatory. – jFrenetic Oct 17 '11 at 06:52
  • Btw, not sure which version of specification you read, but I just took a look at final JPA 2.0 specification for evaluation [here](http://download.oracle.com/otndocs/jcp/persistence-2.0-fr-eval-oth-JSpec/) and it seems that the sentence that you mentioned is in the paragraph 2.12. – jFrenetic Oct 17 '11 at 07:05
  • 1
    You have 7 hours left to write this in separate answer and I will accept it, and award a bounty, which will be lost otherwise :) – jFrenetic Oct 17 '11 at 07:18
  • Done :) Link to JPA spec included. – andbi Oct 17 '11 at 07:26
  • The spec you pointed to is kind of old (now EJB version is **3.1** and **JPA 2.0** was a separate JSR with specification located [here](http://download.oracle.com/otndocs/jcp/persistence-2.0-fr-eval-oth-JSpec/). And the paragraph is 2.12. However I'll award your answer, just please correct it with more up-to-date information. – jFrenetic Oct 17 '11 at 07:44