JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-005Table per subclass with joins(@Inheritance(strategy = InheritanceType.JOINED)、@PrimaryKeyJoinColumn、)

一、结构

The fourth option is to represent inheritance relationships as SQL foreign key associations. Every class/subclass that declares persistent properties—including abstract classes and even interfaces—has its own table.
Unlike the table-per-concrete-class strategy we mapped first, the table of a concrete @Entity here contains columns only for each non-inherited property, declared by the subclass itself, along with a primary key that is also a foreign key of the superclass table.

二、代码

1.

 1 package org.jpwh.model.inheritance.joined;
 2 
 3 import org.jpwh.model.Constants;
 4 
 5 import javax.persistence.Entity;
 6 import javax.persistence.GeneratedValue;
 7 import javax.persistence.Id;
 8 import javax.persistence.Inheritance;
 9 import javax.persistence.InheritanceType;
10 import javax.validation.constraints.NotNull;
11 
12 @Entity
13 @Inheritance(strategy = InheritanceType.JOINED)
14 public abstract class BillingDetails {
15 
16     @Id
17     @GeneratedValue(generator = Constants.ID_GENERATOR)
18     protected Long id;
19 
20     @NotNull
21     protected String owner;
22 
23     // ...
24 
25     protected BillingDetails() {
26     }
27 
28     protected BillingDetails(String owner) {
29         this.owner = owner;
30     }
31 
32     public Long getId() {
33         return id;
34     }
35 
36     public String getOwner() {
37         return owner;
38     }
39 
40     public void setOwner(String owner) {
41         this.owner = owner;
42     }
43 }

2.

 1 package org.jpwh.model.inheritance.joined;
 2 
 3 import javax.persistence.Entity;
 4 import javax.validation.constraints.NotNull;
 5 
 6 @Entity
 7 public class BankAccount extends BillingDetails {
 8 
 9     @NotNull
10     protected String account;
11 
12     @NotNull
13     protected String bankname;
14 
15     @NotNull
16     protected String swift;
17 
18     // ...
19 
20     public BankAccount() {
21         super();
22     }
23 
24     public BankAccount(String owner, String account, String bankname, String swift) {
25         super(owner);
26         this.account = account;
27         this.bankname = bankname;
28         this.swift = swift;
29     }
30 
31     public String getAccount() {
32         return account;
33     }
34 
35     public void setAccount(String account) {
36         this.account = account;
37     }
38 
39     public String getBankname() {
40         return bankname;
41     }
42 
43     public void setBankname(String bankname) {
44         this.bankname = bankname;
45     }
46 
47     public String getSwift() {
48         return swift;
49     }
50 
51     public void setSwift(String swift) {
52         this.swift = swift;
53     }
54 }

3.

 1 package org.jpwh.model.inheritance.joined;
 2 
 3 import javax.persistence.Entity;
 4 import javax.persistence.PrimaryKeyJoinColumn;
 5 import javax.validation.constraints.NotNull;
 6 
 7 @Entity
 8 @PrimaryKeyJoinColumn(name = "CREDITCARD_ID")
 9 public class CreditCard extends BillingDetails {
10 
11     @NotNull
12     protected String cardNumber;
13 
14     @NotNull
15     protected String expMonth;
16 
17     @NotNull
18     protected String expYear;
19 
20     // ...
21 
22     public CreditCard() {
23         super();
24     }
25 
26     public CreditCard(String owner, String cardNumber, String expMonth, String expYear) {
27         super(owner);
28         this.cardNumber = cardNumber;
29         this.expMonth = expMonth;
30         this.expYear = expYear;
31     }
32 
33     public String getCardNumber() {
34         return cardNumber;
35     }
36 
37     public void setCardNumber(String cardNumber) {
38         this.cardNumber = cardNumber;
39     }
40 
41     public String getExpMonth() {
42         return expMonth;
43     }
44 
45     public void setExpMonth(String expMonth) {
46         this.expMonth = expMonth;
47     }
48 
49     public String getExpYear() {
50         return expYear;
51     }
52 
53     public void setExpYear(String expYear) {
54         this.expYear = expYear;
55     }
56 }

4.The primary key columns of the BANKACCOUNT and CREDITCARD tables each also have a foreign key constraint referencing the primary key of the BILLINGDETAILS table.Hibernate relies on an SQL outer join for select bd from BillingDetails bd :

 1 select
 2 BD.ID, BD.OWNER,
 3     CC.EXPMONTH, CC.EXPYEAR, CC.CARDNUMBER,
 4     BA.ACCOUNT, BA.BANKNAME, BA.SWIFT,
 5     case
 6         when CC.CREDITCARD_ID is not null then 1
 7         when BA.ID is not null then 2
 8         when BD.ID is not null then 0
 9     end
10 from BILLINGDETAILS BD
11     left outer join CREDITCARD CC on BD.ID = CC.CREDITCARD_ID
12     left outer join BANKACCOUNT BA on BD.ID = BA.ID

For a narrow subclass query like select cc from CreditCard cc , Hibernate uses an inner join:

1 select
2     CREDITCARD_ID, OWNER, EXPMONTH, EXPYEAR, CARDNUMBER
3 from
4 CREDITCARD
5     inner join BILLINGDETAILS on CREDITCARD_ID=ID

三、优缺点

1.优点

(1)The primary advantage of this strategy is that it normalizes the SQL schema.Schema evolution and integrity-constraint definition are straightforward. A foreign key referencing the table of a particular subclass may represent a polymorphic association to that particular subclass.

2.缺点

more difficult to implement by hand—even ad hoc reporting is more complex.

结论:even though this mapping strategy is deceptively simple, our experience is that performance can be unacceptable for complex class hierarchies. Queries always require a join across many tables, or many sequential reads.

原文地址:https://www.cnblogs.com/shamgod/p/5365745.html