`

JPA 继承

    博客分类:
  • JPA
 
阅读更多

JAP实现继承有三种类型.假设有A.B.C三个类,A为基类,B,C均为A的子类.那么三种设计方式分别为:

 

1.A.B.C共用一张表

 

2.每个类分层结构一张表A.B.C各一张表,各自包含自己的属性.

 

3.A.B.C各一张表.

 

首先,我们针对第一种情况,进行分析.

 

[共用一张表]

 

   首先我们定义基类(本例以文件为例,子类分别为文件夹和文件)

 

  

 

  1. @Entity  
  2. @Inheritance(strategy=InheritanceType.SINGLE_TABLE)  
  3. @Table(name="window_file")  
  4. @DiscriminatorColumn(name="Discriminator",  
  5.                                          discriminatorType = DiscriminatorType.STRING,  
  6.                                          length=30)  
  7. @DiscriminatorValue("WindowFile")  
  8. public class WindowFile {  
  9.       
  10.     @Id  
  11.     @GeneratedValue(strategy = GenerationType.AUTO)  
  12.     private Integer id;  
  13.     @Basic  
  14.     @Column(name="name")  
  15.     private String name;  
  16.       
  17.     @Basic  
  18.     @Column(name="type")  
  19.     private String type;  
  20.       
  21.     @Basic  
  22.     @Column(name="date")  
  23.     private String date;  
  24. //getter setter......  

 

 

 

 分别再定义两个子类:

 

  1. @Entity  
  2. @DiscriminatorValue("Folder")  
  3. public class Folder extends WindowFile {  
  4.   
  5.     @Basic  
  6.     @Column(name="file_count")  
  7.     private Integer fileCount;  
  8.   
  9.     public Integer getFileCount() {  
  10.         return fileCount;  
  11.     }  
  12.   
  13.     public void setFileCount(Integer fileCount) {  
  14.         this.fileCount = fileCount;  
  15.     }  
  16.       
  17.       
  18.       
  19. }  

 

  1. @Entity  
  2. @DiscriminatorValue("Document")  
  3. public class Document extends WindowFile {  
  4.   
  5.     @Basic  
  6.     @Column(name="size")  
  7.     private String size;  
  8.   
  9.     public String getSize() {  
  10.         return size;  
  11.     }  
  12.   
  13.     public void setSize(String size) {  
  14.         this.size = size;  
  15.     }  

 

仔细观查,你会发现,除了基类上指定了@Table属性外,两个子类均没有指定,而且还有几个特殊的地方

 

1>父类中的@Inheritance(strategy=InheritanceType.SINGLE_TABLE):继承表标,指定实现方式为一张表,即所有的对象一张表.

 

2>父类中的@DiscriminatorColumn(name="Discriminator",
                                         discriminatorType = DiscriminatorType.STRING,
                                         length=30) 其实这个字段就是一个区分字段,我们平时自己设计数据库的时候,有时候也会在表中加入一个字段用于判断该记录的类型,那么这个字段就是同样功能,name 为自定义的.

 

3>三个类都有这个注解:@DiscriminatorValue("WindowFile"),很显明,明白了第2>点,这点也很容 易理解,就是上面那个字段的值,当这个字段值为"windowFile"时,他就是基类,为"Document"时,就是Document类....这个 值是自定义的..

 

配置好项目,启动.查看数据库,发现我们的表已经被创建好.表名为"window_file" 有7个字段:Discriminator id date name type file_cout size插入一条纪录,会发现,Discriminator的值是系统自动我们插入的..

 

采用这种式有一个不好的地方:当页面需要进行展示的时候,我们需要对记录的类型的进行判断,因为folder的size为nll  Document类型的file_count为null,不进行判断,则会报nullPointException.而我们的 Discrimination不能在页面上进行获取.所以通常做法是:多加一个字段,可以让其值保持与Discriminator的一样,或者重新创建一 个Dto对象(简单的pojo),拥有这七个属性,专门用与在页面上进行显示,个人比较推荐后面的这种试,原因不多说,既然涉及到hibernate就会 跟session有关,如果session关闭,采用后一种方式在页面上进行展示时也不会报NullPointException.

 

2.每个类分层结构一张表  这种映射方式为每个类创建一个表。在每个类对应的表中只需包含和这个类本身的属性对应的字段,子类对应的表参照父类对应的表,使用每个子类一张表 (table per subclass)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.JOINED
代码如下:

 

 

 

  1. //三个类我一起贴出来..偷下懒  
  2. @Entity  
  3. @Table(name="animal")  
  4. @Inheritance(strategy = InheritanceType.JOINED )  
  5. public class Animal {  
  6.   
  7.     @Id  
  8.     @GeneratedValue(strategy = GenerationType.AUTO)  
  9.     private Integer id;  
  10.       
  11.     @Column(name="name")  
  12.     private String name;  
  13.       
  14.     @Column(name="color")  
  15.     private String color;  
  16.    //getter...setter  
  17. }  
  18.   
  19. @Entity  
  20. @Table(name="bird")  
  21. @PrimaryKeyJoinColumn(name="BirdId")  
  22. public class Bird extends Animal {  
  23.       
  24.     @Column(name="speed")  
  25.     private String speed;  
  26.   
  27.     public String getSpeed() {  
  28.         return speed;  
  29.     }  
  30.   
  31.     public void setSpeed(String speed) {  
  32.         this.speed = speed;  
  33.     }  
  34.       
  35. }  
  36.   
  37. @Entity  
  38. @Table(name="Dog")  
  39. @PrimaryKeyJoinColumn(name="DogId")  
  40. public class Dog extends Animal {  
  41.   
  42.     @Column(name="legs")  
  43.     private Integer legs;  
  44.   
  45.     public Integer getLegs() {  
  46.         return legs;  
  47.     }  
  48.   
  49.     public void setLegs(Integer legs) {  
  50.         this.legs = legs;  
  51.     }  
  52.       
  53.       
  54. }  

 

  

 

  多的不说,看下数据库:生成了三张表,并分别有如下字段

 

animal : id color name

 

bird     : speed birdId(既为主键,又为外键)

 

dog     : legs  dogId(既为主键,又为外键)

 

现在写一个JSP页面,上面有name legs color输入框(即创造一条狗),当我们save成功以后,查看数据库发现animal表有值,dog有值,但bird没有,dog表中的dogId的 值等于animal中的id. 这种方式也就是我们常用的外键设计方式.一般情况下推荐使用这种方式.

 

 

 

3.每个具体类一张表(table per concrete class)
       这种映射方式为每个类创建一个表。在每个类对应的表中包含和这个类所有属性(包括从超类继承的属性)对应的字段,使用每个具体类一张表(table per concrete class)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.TABLE_PER_CLASS
此种方式,代码我就不贴了.. 把Animal中的inheritance改过来.去掉Dog和Bird类中的PrimaryKeyJoinColumn标注.还有一点非常重 要,Animal类的主键生成策略不能自动生成了需要使用@Column(columnDefinition="integer")..进入数据库,删除 animal dog brid三张表.重新编译运行项目.再进入数据库,依然是三张表,不过这三张表和以往的已经不同了..各自都包括了自己应有的属性.什么意思列?父类包含 了自己的属性,而子类包括了从父类继续来的属性..

 

这种方式,不推荐使用,理解有三:

 

1>如果父类的属性特别多,那么在数据量大的时候,会产生很多见冗涂.

 

2>  查询所有Animal时,因为他是最继承树中的根,查询结果会得到所有继承于Animal类的记录

 

     delete from delete from Vehicle  a       执行该操作会删除自身对应记录,还会删除所有继承Vehicle的记录,因为他是最继承树中的根,就相当于清除整个表的数据a       

 

 

 

 

 

 

 

Employee.java:(基类)

 

复制代码
 1 @Entity
 2 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)//选择继承策略
 3 @DiscriminatorColumn(name="type")//配置鉴别器
 4 @DiscriminatorValue("0")//设置鉴别器值
 5 public class Employee {
 6     @Id
 7     @GeneratedValue
 8     private Integer id;
 9     private String name;
10     public Integer getId() {
11         return id;
12     }
13     public void setId(Integer id) {
14         this.id = id;
15     }
16     public String getName() {
17         return name;
18     }
19     public void setName(String name) {
20         this.name = name;
21     }
22 }
复制代码

 

其中@Inheritance(strategy=InheritanceType.SINGLE_TABLE)//选择继承策略 可以选择多种策略,如下图所示:

 

 

  • JOINED:继承的子类各自生成一张表
  • SINGLE_TABLE:只生成一张表,用一个字段当鉴别器
  • TABLE_PER_CLASS:每个类都生产一张表,包括基类

 

 

 

Skiller.java(继承自Employee.java)

 

复制代码
 1 @Entity
 2 @DiscriminatorValue("1")
 3 public class Skiller extends Employee {
 4     private String skill;
 5 
 6     public String getSkill() {
 7         return skill;
 8     }
 9 
10     public void setSkill(String skill) {
11         this.skill = skill;
12     }
13 }
复制代码

 

Sales.java(继承自Employee.java)

 

复制代码
 1 @Entity
 2 @DiscriminatorValue("2")
 3 public class Sales extends Employee {
 4     private String sell;
 5     public String getSell() {
 6         return sell;
 7     }
 8     public void setSell(String sell) {
 9         this.sell = sell;
10     }
11 }
复制代码

 

测试:

 

复制代码
 1     @Test
 2     public void save(){
 3         EntityManagerFactory factory=Persistence.createEntityManagerFactory("sample");
 4         EntityManager em=factory.createEntityManager();
 5         em.getTransaction().begin();
 6         Employee p1=new Employee();
 7         p1.setName("Jim");
 8         Skiller p2=new Skiller();
 9         p2.setName("Hanson");
10         p2.setSkill("skill");
11         Sales p3=new Sales();
12         p3.setName("Brian");
13         p3.setSell("sale");
14         em.persist(p1);
15         em.persist(p2);
16         em.persist(p3);
17         em.getTransaction().commit();
18         em.close();
19         factory.close();
20     }
复制代码

 

打开数据库:

 

 

分享到:
评论

相关推荐

    使用jpa映射关联和继承

    **二、JPA继承映射** 1. **单一继承(Single Table Inheritance,STI)**:所有子类数据都存储在同一个表中,通过一个字段来区分不同的子类。使用`@Inheritance(strategy=InheritanceType.SINGLE_TABLE)`和`@...

    解决 Springboot Jpa 自动创建表 和字段乱序问题[凤凰小哥哥]

    产生原因:因为使用 jpa 自动创建表的时候,采用的是TreeMap的,我们要变成LinkedHashMap 的结构。 解决方案:在项目下java文件夹下创建包名为: org.hibernate.cfg ,创建类: PropertyContainer [包名,类名...

    JPA 实现继承关系

    本篇文章将深入探讨如何在JPA中实现继承关系,这对于构建可扩展且结构化的数据模型至关重要。 在Java中,继承是面向对象编程的一个核心概念,允许一个类(子类)继承另一个类(父类)的属性和方法。在JPA中,继承...

    jpa例子jpajpa

    8. **多态性(Polymorphism)**: JPA支持继承和多态性,使得你可以定义一个基类,然后多个子类继承它并有自己的数据库表。 在"apache-openjpa-1.2.0-source"这个压缩包中,包含了Apache OpenJPA项目的源代码。Open...

    SpringDataJpa开发--继承JpaRepository实现简单条件查询

    本示例主要探讨如何通过继承`JpaRepository`接口来实现简单的条件查询。`JpaRepository`是Spring Data JPA提供的一种高级抽象,它允许我们以声明式的方式处理CRUD操作,以及执行基本的查询。 首先,我们需要理解`...

    spring-boot-jpa-hibernate-demo:Spring Boot中的JPA + Hibernate + MySQL

    JPA 使用 Hibernate 作为实现方式JPA + Hibernate + MySQL in Spring Boot注意此项目使用spring-boot 1.4.0版本,不适用于spring-boot 2.0 版本;2.0版本的项目配置可参考:本项目使用IDEA构建,直接导入IDEA即可...

    jpa/hibernate继承注解

    在Java Persistence API (JPA) 和 Hibernate ORM 框架中,继承注解是用于处理对象关系映射(ORM)中的类继承结构的关键概念。这些注解帮助开发者将数据库表的设计与面向对象的代码结构相匹配,使得在复杂的业务场景...

    spring-jpa-inheritance

    Spring JPA继承是处理数据库表继承关系的一种方式,允许我们在对象模型中定义继承结构,并将这些映射到数据库中的表。这种方式有助于保持代码的整洁和可维护性,同时还能利用数据库的特性来优化查询性能。 首先,...

    JPA 标注 JPA标签手册

    Java Persistence API (JPA) 是Java企业版5(Java EE 5)的一部分,与Enterprise JavaBeans(EJB)3.0规范一起,极大地简化了Java持久化。它提供了一种对象关系映射方法,允许您以标准、可移植的方式声明性地定义...

    JPA视频教程_使用jpa映射关联和继承

    在这个**“JPA视频教程_使用jpa映射关联和继承”**中,我们将深入探讨如何利用JPA来处理实体之间的关联和类的继承关系。 **1. JPA 注解** JPA 注解是实现ORM的主要手段,它们可以直接在实体类上声明,用于定义...

    JPA详细文档(JPA 批注参考)

    Java 持续性API(JPA)是Java EE 5和Enterprise JavaBean(EJB)3.0规范的一部分,其主要目标是简化EJB的持久化操作,并提供了一种对象关系映射(ORM)机制,允许开发者以声明式方式定义Java对象如何映射到关系...

    Spring Data JPA 简化 JPA 开发

    2. CrudRepository:继承自 Repository,提供了基本的 CRUD 功能,如 save、delete、findById 等。 3. PagingAndSortingRepository:扩展自 CrudRepository,增加了分页和排序的能力。 4. JpaRepository:是 ...

    jpa经典文档呀

    7. **继承映射**:JPA允许实体类继承,提供了单表继承、联合继承和多表继承等多种策略。 8. **关联映射**:JPA支持一对一、一对多、多对一和多对多的关系映射,通过@OneToOne、@OneToMany、@ManyToOne和@ManyToMany...

    Spring Data JPA 笔记

    通过继承`JpaRepository`或自定义Repository接口,可以轻松实现数据访问。例如,`findById`、`save`等方法都由Spring Data JPA自动提供。 3. **Querydsl**:Spring Data JPA可以与Querydsl结合使用,提供更强大的...

    JPA讲解视频

    8. **继承映射(Inheritance Mapping)**:JPA支持单表继承、联合继承和表格分层等策略,使你可以设计复杂的对象模型。 9. **懒加载(Lazy Loading)**:默认情况下,JPA实现如Hibernate支持懒加载,即关联的对象只...

    jpa

    5. **多态性**:支持子类继承父类实体,并在数据库中统一存储。 6. **查询语言**:JPQL和 Criteria 查询提供灵活的数据检索方式。 结合标签“工具”,我们可以想到JPA在实际开发中的应用场景,如Spring框架中的...

    JPA大全之经典全集

    例如,使用`EntityManager`进行数据的增删改查,利用`JPQL`(Java Persistence Query Language)或`Criteria API`进行查询,以及如何处理关联关系和继承结构等。此外,还会讲解如何在Spring框架中集成JPA,使用`...

    学习hibernate必读,JPA2新特征和JPA2映射的神秘之旅。

    - **继承映射**:支持单表继承(Single Table Inheritance)、联合继承(Joined Table Inheritance)和表-per-class-hierarchy策略。 - **关联映射的级联操作**:如`CascadeType.ALL`,可将操作自动应用到关联的...

    JPA (一)

    这些类通常会继承 `javax.persistence.Entity`,并且通过 `@Entity` 注解标记。实体类中的属性对应于数据库表的列。 2. **实体管理器(EntityManager)** - 它是 JPA 的核心组件,负责与数据库交互。它创建、更新、...

Global site tag (gtag.js) - Google Analytics