JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-004Table per class hierarchy(@Inheritance..SINGLE_TABLE)、@DiscriminatorColumn、@DiscriminatorValue、@DiscriminatorFormula)
2016-04-07 21:40
435 查看
一、结构
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.
2.
3.
4.在无法改变表结构增加discriminator的情况下,可以使用Hibernate的扩展注解@DiscriminatorFormula,底层是利用数据库的case when 语句
三、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 :
To query the CreditCard subclass, Hibernate adds a restriction on the discriminator column:
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.
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.
package org.jpwh.model.inheritance.singletable; import org.jpwh.model.Constants; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.validation.constraints.NotNull; @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "BD_TYPE") public abstract class BillingDetails { @Id @GeneratedValue(generator = Constants.ID_GENERATOR) protected Long id; @NotNull // Ignored by Hibernate for schema generation! @Column(nullable = false) protected String owner; // ... protected BillingDetails() { } protected BillingDetails(String owner) { this.owner = owner; } public Long getId() { return id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
2.
package org.jpwh.model.inheritance.singletable; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.validation.constraints.NotNull; @Entity @DiscriminatorValue("BA") public class BankAccount extends BillingDetails { @NotNull protected String account; @NotNull protected String bankName; @NotNull protected String swift; public BankAccount() { super(); } public BankAccount(String owner, String account, String bankName, String swift) { super(owner); this.account = account; this.bankName = bankName; this.swift = swift; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getBankName() { return bankName; } public void setBankName(String bankName) { this.bankName = bankName; } public String getSwift() { return swift; } public void setSwift(String swift) { this.swift = swift; } }
3.
package org.jpwh.model.inheritance.singletable; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.validation.constraints.NotNull; @Entity @DiscriminatorValue("CC") public class CreditCard extends BillingDetails { @NotNull // Ignored by Hibernate for DDL generation! protected String cardNumber; @NotNull protected String expMonth; @NotNull protected String expYear; // ... public CreditCard() { super(); } public CreditCard(String owner, String cardNumber, String expMonth, String expYear) { super(owner); this.cardNumber = cardNumber; this.expMonth = expMonth; this.expYear = expYear; } public String getCardNumber() { return cardNumber; } public void setCardNumber(String cardNumber) { this.cardNumber = cardNumber; } public String getExpMonth() { return expMonth; } public void setExpMonth(String expMonth) { this.expMonth = expMonth; } public String getExpYear() { return expYear; } public void setExpYear(String expYear) { this.expYear = expYear; } }
4.在无法改变表结构增加discriminator的情况下,可以使用Hibernate的扩展注解@DiscriminatorFormula,底层是利用数据库的case when 语句
package org.jpwh.model.inheritance.singletableformula; import org.jpwh.model.Constants; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.validation.constraints.NotNull; @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @org.hibernate.annotations.DiscriminatorFormula( "case when CARDNUMBER is not null then 'CC' else 'BA' end" ) public abstract class BillingDetails { // ... @Id @GeneratedValue(generator = Constants.ID_GENERATOR) protected Long id; @NotNull protected String owner; protected BillingDetails() { } protected BillingDetails(String owner) { this.owner = owner; } public Long getId() { return id; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
三、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 :
select ID, OWNER, EXPMONTH, EXPYEAR, CARDNUMBER, ACCOUNT, BANKNAME, SWIFT, BD_TYPE from BILLINGDETAILS
To query the CreditCard subclass, Hibernate adds a restriction on the discriminator column:
select ID, OWNER, EXPMONTH, EXPYEAR, CARDNUMBER from BILLINGDETAILS where 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.
相关文章推荐
- 关于intent.setFlags()的一些故事
- Android-通过Java代码来实现属性动画
- Cocos2d-x学习笔记(10)(CCMenu菜单)
- android工具库
- 自己实现android侧滑菜单
- Android开发-layout布局相关属性总结
- Android Studio连接华为mate8手机调试时不显示错误日志的解决办法
- iOS AFNetWorking中block执行完后再执行其它操作
- [android] 手机卫士关闭自动更新
- Android编程学习笔记 之 BroadcastReceiver组件
- poj 2385 Apple Catching 基础dp
- Android -- Camera2(Android5.0)
- android和iOS的.gitignore模版
- 浅谈iOS模糊效果
- Android应用一般上架流程
- [Android]从视频流读取帧图像保存到本地
- Android自定义View或ViewGroup的流程
- JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-003Table per concrete class with unions(@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)、<union-subclass>)
- everything is object
- Android开发文档翻译之——Bound Services