`
lwt_cedric
  • 浏览: 114944 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

JPA继承详解(转)

    博客分类:
  • java
阅读更多

因为关系数据库的表之间不存在继承关系,Entity 提供三种基本的继承映射策略:
每个类分层结构一张表(table per class hierarchy)
每个子类一张表(table per subclass)
每个具体类一张表(table per concrete class)

一、每个类分层结构一张表(table per class hierarchy)
       这种映射方式只需为基类创建一个表即可。在表中不仅提供基类所有属性对应的字段,还要提供所有子类属性对应的字段,此外还需要一个字段用于区分子类的具体类型要使用每个类分层结构一张表(table per class hierarchy) 策略,需要把@javax.persistence.Inheritance 注释的strategy属性设置为InheritanceType.SINGLE_TABLE。除非你要改变子类的映射策略,否则@Inheritance 注释只能放在继承层次的基类。通过鉴别字段的值,持久化引掣可以区分出各个类,并且知道每个类对应那些字段。鉴别字段通过@javax.persistence.DiscriminatorColumn 注释进行定义,name 属性定义鉴别字段的列名,discriminatorType 属性定义鉴别字段的类型(可选值有:String, Char, Integer),如果鉴别字段的类型为String 或Char,可以用length 属性定义其长度。@DiscriminatorValue 注释为继承关系中的每个类定义鉴别值,如果不指定鉴别值,默认采用类名
例:
    @SuppressWarnings("serial")
    @Entity
    @Table(name="Vehicle_Hierarchy")
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn(name="Discriminator",
                                         discriminatorType = DiscriminatorType.STRING,
                                         length=30)
    @DiscriminatorValue("Vehicle")
    public class Vehicle implements Serializable{       //基类
    private Long id;
    private Short speed;//速度
    @Id
    @GeneratedValue
    @Column(columnDefinition="integer")//指定使用适配Integer长度的数据类型
    public Long getId() {
    return id;
    }
    public void setId(Long id) {
    this.id = id;
    }

    @SuppressWarnings("serial")
    @Entity
    @DiscriminatorValue("Car")
    public class Car extends Vehicle{        //Vehicle的子类
    private String engine;//发动机
    @Column(nullable=true,length=30)
    public String getEngine() {
    return engine;
    }
    public void setEngine(String engine) {
    this.engine = engine;
        }
    }


     @SuppressWarnings("serial")
     @Entity
     @DiscriminatorValue("Camion")
     public class Camion extends Car{         //Car的子类
     private String container;//集装箱
     @Column(nullable=true,length=30)
     public String getContainer() {
     return container;
     }
     public void setContainer(String container) {
     this.container = container;
          }
     }
分析:
       可以看出,每个子类没有单独的映射,在数据库中没有对应的表存在。而只有一个记录所有自身属性和子类所有属性的表,在基类为Vehicle 的时候,Discriminator 字段的值将为Vehicle,在子类为Car 的时候,Discriminator 字段的值将为Car,子类为Camion 的时候,Discriminator 字段的值将为Camion。那么,如果业务逻辑要求Car 对象的engine 属性不允许为null,显然无法在Vehicle_Hierarchy 表中为engine 字段定义not null 约束,可见这种映射方式无法保证关系数据模型的数据完整性。

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

     @SuppressWarnings("serial")
     @Entity
     @Inheritance(strategy=InheritanceType.JOINED)
     @Table(name="Vehicle")
     public class Vehicle implements Serializable{      //基类
     private Long id;
     private Short speed;//速度
     @Id
     @GeneratedValue
     @Column(columnDefinition="integer")
     public Long getId() {
     return id;
     }
     public void setId(Long id) {
     this.id = id;
     }
     public Short getSpeed() {
     return speed;
     }
     public void setSpeed(Short speed) {
     this.speed = speed;
     }
     }

     @SuppressWarnings("serial")
     @Entity
     @Table(name="Car")
     @PrimaryKeyJoinColumn(name="CarID")     //把主键对应的列名更改为CarID
     public class Car extends Vehicle{                 //Vehicle的子类
     private String engine;//发动机
     @Column(nullable=true,length=30)
     public String getEngine() {
     return engine;
     }
     public void setEngine(String engine) {
     this.engine = engine;
     }
     }

     @SuppressWarnings("serial")
     @Entity
     @Table(name="Camion")
     @PrimaryKeyJoinColumn(name="CamionID")     //把主键对应的列名更改为CamionID
     public class Camion extends Car{                    //Car的子类
     private String container;
     @Column(nullable=true,length=30)
     public String getContainer() {
     return container;
     }
     public void setContainer(String container) {
     this.container = container;
     }
     }
        这种映射方式支持多态关联和多态查询,而且符合关系数据模型的常规设计规则。在这种策略中你可以对子类的属性对应的字段定义not null 约束。该策略的缺点:
        它的查询性能不如上面介绍的映射策略。在这种映射策略下,必须通过表的内连接或左外连接来实现多态查询和多态关联。
选择原则:子类属性非常多,需要对子类某些属性对应的字段进行not null 约束,且对性能要求不是很严格时,优先选择该策略

三、每个具体类一张表(table per concrete class)
       这种映射方式为每个类创建一个表。在每个类对应的表中包含和这个类所有属性(包括从超类继承的属性)对应的字段,使用每个具体类一张表(table per concrete class)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.TABLE_PER_CLASS

        注意:一旦使用这种策略就意味着你不能使用AUTO generator 和IDENTITY generator,即主键值不能采用数据库自动生成.

     @SuppressWarnings("serial")
     @Entity
     @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
     @Table(name="Vehicle")
     public class Vehicle implements Serializable{            //基类
     private Long id;
     private Short speed;//速度
     @Id
     @Column(columnDefinition="integer")
     public Long getId() {
     return id;
     }
     public void setId(Long id) {
     this.id = id;
     }
     public Short getSpeed() {
     return speed;
     }
     public void setSpeed(Short speed) {
     this.speed = speed;
     }
     }

     @SuppressWarnings("serial")
     @Entity
     @Table(name="Car")
    public class Car extends Vehicle{               //Vehicle的子类
     private String engine;//发动机
     @Column(nullable=true,length=30)
     public String getEngine() {
     return engine;
     }
     public void setEngine(String engine) {
     this.engine = engine;
     }
     }

     @SuppressWarnings("serial")
     @Entity
     @Table(name="Camion")
     public class Camion extends Car{              //Car的子类
     private String container;//集装箱
     @Column(nullable=true,length=30)
     public String getContainer() {
     return container;
     }
     public void setContainer(String container) {
     this.container = container;
     }
     }

注意:在查询时,例如: from Vehicle v
         查询所有Vehicle时,因为他是最继承树中的根,查询结果会得到所有继承于Vehicle类的记录
(构造的SQL Where部分:where Discriminator in ('Car', 'Camion'))
         delete from Vehicle v
         执行该操作会删除自身对应记录,还会删除所有继承Vehicle的记录,因为他是最继承树中的根,就相当于清除整个表的数据

该策略的优点:
                     在这种策略中你可以对子类的属性对应的字段定义not null 约束。
该策略的缺点:
                     不符合关系数据模型的常规设计规则,每个表中都存在属于基类的多余的字段。同时,为了支持策略的映射,持久化管理者需要决定使用什么方法,一种方法是在 entity 载入或多态关联时,容器使用多次查询去实现,这种方法需要对数据库做几次来往查询,非常影响执行效率。另一种方法是容器通过使用SQLUNIOU 查询来实现这种策略。
选择原则:
                     除非你的现实情况必须使用这种策略,一般情况下不要选择。

 

分享到:
评论

相关推荐

    jpa注解详解

    JPA注解详解 JPA(Java Persistence API)是Java企业版5(Java EE 5)的一部分,提供了一个对象关系映射方法,使得开发者可以使用声明方式定义如何将Java对象映射到关系数据库表。在JPA中,批注是一种使用元数据...

    JPA详解视频教程 第19讲 映射关联和继承.avi

    JPA用于整合现有的ORM技术,可以简化现有Java EE和Java SE应用对象持久化的开发工作,实现ORM的统一。JPA详解视频教程 第19讲 映射关联和继承.avi

    java程序使用JPA注解详解.zip

    JPA还提供了Repository接口,通过继承该接口,我们可以实现对实体的CRUD操作,而无需手动编写DAO层代码。此外,Querydsl、Spring Data JPA等库进一步扩展了JPA的功能,使查询更加简洁和强大。 总之,JPA注解大大...

    03_JPA详解_搭建JPA开发环境和全局事务介绍.zip

    5. **Repository接口**: 使用Spring Data JPA,我们可以创建一个Repository接口,该接口继承自JpaRepository或CrudRepository,提供基本的CRUD操作: ```java public interface UserRepository extends Jpa...

    03_传智播客JPA详解_搭建JPA开发环境和全局事务介绍

    了解以上基础后,你可以观看"03_传智播客JPA详解_搭建JPA开发环境和全局事务介绍"的自学视频,视频将更深入地展示如何操作和实践。学习过程中,你将看到如何配置JPA环境,创建并管理实体,以及如何在实际项目中运用...

    09_JPA详解_使用JPQL语句进行查询.zip

    6. **继承(Inheritance)**:JPA支持单表继承、联合继承和表-per-hierarchy等多种继承策略,这使得能够根据业务需求灵活设计实体结构。 7. **懒加载与急加载(Lazy vs. Eager Loading)**:默认情况下,关联是懒...

    springboot整合jpa

    - **配置Repository**:Spring Data JPA提供了自动化的数据访问接口,只需要定义接口继承`JpaRepository`,即可进行基本的CRUD操作。 - **启动H2 Console(可选)**:SpringBoot默认集成了H2数据库,可以在开发...

    02_传智播客JPA详解_JPA开发环境和思想介绍

    - **继承(Inheritance)**:支持类继承关系的映射,如单表继承、联合继承、表格派生。 - **查询语言(JPQL)**:类似SQL的查询语言,用于在对象层进行查询。 - ** Criteria API**:提供动态构建查询的能力,比JPQL更...

    14_传智播客JPA详解_JPA中的多对多双向关联的各项关系操作

    8. **Inheritance策略**:如果实体类继承自其他类,需考虑JPA的继承策略(如SINGLE_TABLE、JOINED、TABLE_PER_CLASS),这可能会影响到多对多关联的实现。 9. **事务管理**:由于多对多关联的修改可能涉及到多个...

    JPA讲解视频

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

    JPA大全之经典全集

    JPA详解通常是对JPA的深入解析,包括实体(Entity)、持久化上下文(Persistence Context)、托管状态(Managed State)、懒加载(Lazy Loading)、级联操作(Cascading)、关系映射(Relationship Mapping)、查询...

    JPA (一)

    **Java 持久化 API(JPA)详解(一)** Java 持久化 API(Java Persistence API),简称 JPA,是 Java 平台上的一个标准,用于管理关系数据库中的数据。JPA 提供了一种面向对象的方式来操作数据库,使得开发人员...

    JPA注解(转)

    **JPA注解详解** Java Persistence API(JPA)是Java平台上的一个标准,用于管理关系数据库中的数据。它提供了一种对象/关系映射(ORM)机制,使得开发人员可以使用面向对象的编程方式来操作数据库。在JPA中,注解...

    spring-data-jpa-examples

    《Spring Data JPA 实战详解》 Spring Data JPA 是 Spring 框架的一个重要模块,它为 Java Persistence API (JPA) 提供了统一的数据访问接口,简化了数据库操作。在 "spring-data-jpa-examples" 这个项目中,我们将...

    JPA教程(全部为PDF格式的电子书)

    3. **继承和多态性**:讲解如何处理实体类的继承关系,以及多态查询。 4. **转换和事件**:介绍实体状态转换和生命周期事件,如预加载、加载、保存、更新和删除事件。 5. **异步和并发**:讨论并发控制策略,如乐观...

    Spring-JPA

    **Spring-JPA 知识点详解** Spring-JPA,全称Spring Data JPA,是Spring框架的一个模块,它为Java Persistence API (JPA) 提供了面向切面的编程(AOP)支持,使得在Spring应用中使用JPA变得更加简单。JPA本身是Java...

    整合Spring Data JPA1

    【Spring Data JPA 知识点详解】 Spring Data JPA 是 Spring Data 框架的一个重要组成部分,它为 Java 持久层提供了一种基于 JPA(Java Persistence API)的简单、高效的解决方案。JPA 是 Java 标准,用于管理关系...

    详解SpringBoot实现JPA的save方法不更新null属性

    为了实现上述思路,可以创建一个通用 CRUD 实现类,继承自 SimpleJpaRepository。这个类需要实现 save 方法,以便处理 null 属性的问题。 知识点 4: save 方法的实现 在 save 方法中,首先需要获取对象的 ID,如果...

Global site tag (gtag.js) - Google Analytics