JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-004Table per class hierarchy(@Inheritance..SINGLE_TABLE)、@DiscriminatorColumn、@DiscriminatorValue、@DiscriminatorFormula)

一、结构

You can map an entire class hierarchy to a single table. This table includes columns for all properties of all classes in the hierarchy. The value of an extra type discriminator column or formula identifies the concrete subclass represented by a particular row. Figure 6.2 shows this approach.

二、代码

1.

 1 package org.jpwh.model.inheritance.singletable;
 2
 3 import org.jpwh.model.Constants;
 4
 5 import javax.persistence.Column;
 6 import javax.persistence.DiscriminatorColumn;
 7 import javax.persistence.Entity;
 8 import javax.persistence.GeneratedValue;
 9 import javax.persistence.Id;
10 import javax.persistence.Inheritance;
11 import javax.persistence.InheritanceType;
12 import javax.validation.constraints.NotNull;
13
14 @Entity
15 @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
16 @DiscriminatorColumn(name = "BD_TYPE")
17 public abstract class BillingDetails {
18
19     @Id
20     @GeneratedValue(generator = Constants.ID_GENERATOR)
21     protected Long id;
22
23     @NotNull // Ignored by Hibernate for schema generation!
24     @Column(nullable = false)
25     protected String owner;
26
27     // ...
28
29     protected BillingDetails() {
30     }
31
32     protected BillingDetails(String owner) {
33         this.owner = owner;
34     }
35
36     public Long getId() {
37         return id;
38     }
39
40     public String getOwner() {
41         return owner;
42     }
43
44     public void setOwner(String owner) {
45         this.owner = owner;
46     }
47 }

2.

 1 package org.jpwh.model.inheritance.singletable;
 2
 3 import javax.persistence.DiscriminatorValue;
 4 import javax.persistence.Entity;
 5 import javax.validation.constraints.NotNull;
 6
 7 @Entity
 8 @DiscriminatorValue("BA")
 9 public class BankAccount extends BillingDetails {
10
11     @NotNull
12     protected String account;
13
14     @NotNull
15     protected String bankName;
16
17     @NotNull
18     protected String swift;
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.singletable;
 2
 3 import javax.persistence.DiscriminatorValue;
 4 import javax.persistence.Entity;
 5 import javax.validation.constraints.NotNull;
 6
 7 @Entity
 8 @DiscriminatorValue("CC")
 9 public class CreditCard extends BillingDetails {
10
11     @NotNull // Ignored by Hibernate for DDL generation!
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.在无法改变表结构增加discriminator的情况下,可以使用Hibernate的扩展注解@DiscriminatorFormula,底层是利用数据库的case when 语句

 1 package org.jpwh.model.inheritance.singletableformula;
 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.SINGLE_TABLE)
14 @org.hibernate.annotations.DiscriminatorFormula(
15         "case when CARDNUMBER is not null then ‘CC‘ else ‘BA‘ end"
16 )
17 public abstract class BillingDetails {
18     // ...
19     @Id
20     @GeneratedValue(generator = Constants.ID_GENERATOR)
21     protected Long id;
22
23     @NotNull
24     protected String owner;
25
26     protected BillingDetails() {
27     }
28
29     protected BillingDetails(String owner) {
30         this.owner = owner;
31     }
32
33     public Long getId() {
34         return id;
35     }
36
37     public String getOwner() {
38         return owner;
39     }
40
41     public void setOwner(String owner) {
42         this.owner = owner;
43     }
44 }

三、SINGLE_TABLE的优缺点

1.优点

(1)This mapping strategy is a winner in terms of both performance and simplicity. It’s the best-performing way to represent polymorphism—both polymorphic and non-polymorphic queries perform well—and it’s even easy to write queries by hand. Ad hoc reporting is possible without complex joins or unions. Schema evolution is straightforward.

Hibernate generates the following  SQL for  select bd from BillingDetails bd :

1 select
2     ID, OWNER, EXPMONTH, EXPYEAR, CARDNUMBER,
3     ACCOUNT, BANKNAME, SWIFT, BD_TYPE
4 from
5     BILLINGDETAILS

To query the CreditCard subclass, Hibernate adds a restriction on the discriminator column:

1 select
2     ID, OWNER, EXPMONTH, EXPYEAR, CARDNUMBER
3 from
4     BILLINGDETAILS
5 where
6     BD_TYPE=‘CC‘

2.缺点

(1)the loss of NOT NULL constraints may be a serious problem from the point of view of data correctness. Imagine that an expiration date for credit cards is required, but your database schema can’t enforce this rule because all columns of the table can be NULL .

(2)Another important issue is normalization. You’ve created functional dependencies between non-key columns, violating the third normal form. As always, denormalization for performance reasons can be misleading, because it sacrifices long-term stability,maintainability, and the integrity of data for immediate gains that may be also achieved
by proper optimization of the SQL execution plans (in other words, ask your DBA ).

(3)considering denormalized schemas can become a major burden in the long term. Your DBA may not like it at all

(4)An implementation quirk of Hibernate requires that you declare nullability with @Column because Hibernate
ignores Bean Validation’s @NotNull when it generates the database schema.Hibernate ignores the @NotNull for schema DDL generation, but it observes it at runtime, before inserting a row.

时间: 2024-10-20 21:13:03

JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-004Table per class hierarchy(@Inheritance..SINGLE_TABLE)、@DiscriminatorColumn、@DiscriminatorValue、@DiscriminatorFormula)的相关文章

JavaPersistenceWithHibernate第二版笔记-第五章-Mapping value types-004嵌套组件的注解AttributeOverrides

一.数据库 二.代码 1. 1 package org.jpwh.model.advanced; 2 3 import javax.persistence.AttributeOverride; 4 import javax.persistence.AttributeOverrides; 5 import javax.persistence.Column; 6 import javax.persistence.Embeddable; 7 import javax.validation.constr

JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-003映射实体时的可选操作(<delimited-identifiers/>、PhysicalNamingStrategy、PhysicalNamingStrategyStandardImpl、、、)

一.自定义映射的表名 1. 1 @Entity 2 @Table(name = "USERS") 3 public class User implements Serializable { 4 // ... 5 } 2.用定界符 1 //@Table(name = "`USER`")的标准 2 @Table(name = "`USER`") 3 4 //JPA的标准 5 @Table(name = "\"USER\"

JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-001区分entities and value types

一.介绍 1.这种引用方式不对,但删除时不能级联 要这种引用方式 2.The Bid class could be a problem. In object-oriented modeling, this is marked as a composition (the association between Item and Bid with the diamond). Thus, an Item is the owner of its Bid instances and holds a col

JavaPersistenceWithHibernate第二版笔记-第四章-Mapping persistent classes-002identity详解

一.简介 1.You now have three methods for distinguishing references: ? Objects are identical if they occupy the same memory location in the JVM . This can be checked with the a == b operator. This concept is known as object identity.? Objects are equal i

JavaPersistenceWithHibernate第二版笔记-第七章-004Mapping a map(@MapKeyEnumerated 、 @MapKeyTemporal、@MapKeyColumn)

一.结构 二.代码 1. 1 package org.jpwh.model.collections.mapofstrings; 2 3 import org.jpwh.model.Constants; 4 5 import javax.persistence.CollectionTable; 6 import javax.persistence.Column; 7 import javax.persistence.ElementCollection; 8 import javax.persist

JavaPersistenceWithHibernate第二版笔记-第七章-003Mapping an identifier bag(@OrderColumn、@ElementCollection、@CollectionTable、、)

一.结构 二.代码 1. 1 package org.jpwh.model.collections.listofstrings; 2 3 import org.jpwh.model.Constants; 4 5 import javax.persistence.CollectionTable; 6 import javax.persistence.Column; 7 import javax.persistence.ElementCollection; 8 import javax.persis

JavaPersistenceWithHibernate第二版笔记-第七章-001Mapping a set(@ElementCollection、@CollectionTable、@JoinColumn、)

一.结构 二.代码 1. 1 package org.jpwh.model.collections.setofstrings; 2 3 import org.jpwh.model.Constants; 4 5 import javax.persistence.CollectionTable; 6 import javax.persistence.Column; 7 import javax.persistence.ElementCollection; 8 import javax.persist

Python核心编程(第二版) 第六章习题答案

6–1.字符串.string 模块中是否有一种字符串方法或者函数可以帮我鉴定一下一个字符串是否是另一个大字符串的一部分? 答:有,string.find(str,beg,end) 6–2.字符串标识符.修改例 6-1 的 idcheck.py 脚本,使之可以检测长度为一的标识符,并且可以识别 Python 关键字,对后一个要求,你可以使用 keyword 模块(特别是 keyword.kelist)来帮你. 1 #!/usr/bin/python 2 3 import string 4 impo

读书笔记--《Python基础教程第二版》--第六章 抽象

6.1 懒惰即美德 >>> fibs=[0,1] >>> for i in range(8): ...  fibs.append(fibs[-2]+fibs[-1]) ... >>> fibs [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 6.2 抽象和结构 page=download_page() freqs=compute_frequencies(page) for word,freq in freqs: print word