惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

博客园 - eafy.ye

Java获取系统信息(cpu,内存,硬盘,进程等)的相关方法 url参数中传递中文 - eafy.ye - 博客园 cglib介绍(转) openfire消息包接受处理流程&Openfire Plugins加载流程 eclipse中开发openfire 垃圾收集器与Java编程(转) Struts2的工作机制及分析(转) Freemarker caching of BeanWrapper models java传递是引用的拷贝,既不是引用本身,更不是对象 open session and Hibernate事务处理机制 奥运会开幕 Acegi集成CAS hibernate annotations和hbm.xml配置文件在spring中的并存配置 jBPM-jPDL学习笔记——流程设计与控制(转) JMock来实现孤立测试(转) jBPM开发入门指南 JAVA动态代理实现&&动态字节码生成(asm) java与Groovy的整合 Dom4j 使用简介
Hibernate/JPA中的继承映射
eafy.ye · 2008-09-23 · via 博客园 - eafy.ye


Hibernate的继承映射包含了三种不同的策略:

  1. 每簇类使用一个表;
  2. 每个子类一个表;
  3. 每个具体内一个表(有限制)。

假设我们有四个类Animal,Dog,Cat,其代码如下:
文件名:Animal.java


文件名:Dog.java


文件名:Cat.java

  • 每簇类使用一个表

       使用每簇类使用一个表的策略时,有一个限制就时子类不能有NOT NULL,映射文件为:
       文件名:Animal.hbm.xml

  • 每个子类一个表

       使用每个子类一个表的策略时,可以使用一个映射文件实现,也可以分成多个映射文件来实现。每个子类一个映射文件的情况:
       文件名:Animal.hbm.xml


       每个子类一个表的策略实际上一种one-to-one的映射。

  • 每个具体内一个表(有限制)

       使用每个具体内一个表(有限制)策略时,每一个子类的映射文件将要包含所有父类中的属性,映射文件:
       文件名:Dog.hbm.xml

JPA中的实体层次设计

这部分的内容基本与Hibernate一致.JPA同样支持3种类型的继承形式:

1.Single Table Strategy ,单表策略,一张表包含基类与子类的所有数据,很多情况下都是采用这样的冗余设计,通过一个discriminator来区分

2.Table Per Class Strategy ,每个子类对应一张表,每张表都拥有基类的属性

3.Join Strategy ,仍然是每个子类对应一张表,但此表中不包含基类的属性,仅仅是此子类的扩展属性,共享基类的属性

以一个例子来说明3种情况:

一.单表策略

比如Pet作为基类,Cat和Dog继承此类并拥有自己的扩展属性,如:

package com.denny_blue.ejb3.inheritance;

import java.io.Serializable;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

 public Pet() {
 }

 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public double getWeight() {
  return weight;
 }

 public void setWeight(double weight) {
  this.weight = weight;
 }

}

Pet类值的注意的就是通过@Inheritance(strategy = InheritanceType.SINGLE_TABLE)确定采用单表策略,通过@DiscriminatorColumn确定了标志值的字段和类型,我想熟悉hibernate的朋友对这些都应该很熟悉.然后是两个子类:

//Cat.java

package com.denny_blue.ejb3.inheritance;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue("cat")
public class Cat extends Pet {
 private String HairBall;

 public String getHairBall() {
  return HairBall;
 }

 public void setHairBall(String hairBall) {
  HairBall = hairBall;
 }

}

//Dog.java

package com.denny_blue.ejb3.inheritance;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("dog")
public class Dog extends Pet {
 private String trick;

 public String getTrick() {
  return trick;
 }

 public void setTrick(String trick) {
  this.trick = trick;
 }

}

两个子类最值的关注的就是@DiscriminatorValue注释,比如Cat的此值为cat,意味着当Cat类型的Entity存入数据库时,JPA将自动把cat的值赋给animal_type字段,Dog的值则为dog,由此就可以在同一张表中区分开两个不同的子类.

二.Table per Class

采用Table Per Class策略的话,每个子类都将单独建表,并且都独立拥有基类中的所有属性,互相之间不共享,在我们的例子中所要进行的修改很小,像这样:

//基类

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

........

//子类:不需要任何设置

@Entity
public class Dog extends Pet {
 private String trick;

  .......

  .......

三.Join策略

每个子类同样独立建表,基类也独立建表,只不过所有的子类的表中只有扩展属性,他们共享基类的表,在我们的例子中修改下即可:

//基类

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Pet implements Serializable {
 private int id;

 private String name;

 private double weight;

  ........

//子类

@Entity

@Inheritance(strategy = InheritanceType.JOINED)
public class Dog extends Pet {
 private String trick;