• EJB>实体继承


    三个类分别是:Vehicle(交通工具),Car(汽车),Camion(卡车),他们的继承关系如下:

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

    一、每个类分层结构一张表(table per class hierarchy)

    这种映射方式只需为基类Vehicle 创建一个表(Vehicle_Hierarchy)即可。在表中不仅提供Vehicle 所有属性对应的字段,还要提供所有子类属性对应的字段,此外还需要一个字段用于区分子类的具体类型。

    要使用每个类分层结构一张表(table per class hierarchy) 策略,需要把@javax.persistence.Inheritance 注释的strategy属性设置为InheritanceType.SINGLE_TABLE。除非你要改变子类的映射策略,否则@Inheritance 注释只能放在继承层次的基类。通过鉴别字段的值,持久化引掣可以区分出各个类,并且知道每个类对应那些字段鉴别字段通过@javax.persistence.DiscriminatorColumn 注释进行定义,name 属性定义鉴别字段的列名,discriminatorType 属性定义鉴别字段的类型(可选值有:String, Char, Integer),如果鉴别字段的类型为String 或Char,可以用length 属性定义其长度。@DiscriminatorValue 注释为继承关系中的每个类定义鉴别值,如果不指定鉴别值,默认采用类名。

    Vehicle.java

    package com.foshanshop.ejb3.bean;
    
    import java.io.Serializable;
    
    import javax.persistence.DiscriminatorColumn;
    import javax.persistence.DiscriminatorType;
    import javax.persistence.DiscriminatorValue;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Inheritance;
    import javax.persistence.InheritanceType;
    import javax.persistence.Table;
    
    @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 static final long serialVersionUID = -3196397365804550797L;
    private Long id;
        private Short speed;//速度
        
        @Id
        @GeneratedValue
        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;
        }
    }
    


     Car.java( Car 继承Vehicle,并有自己的属性engine) 

    package com.foshanshop.ejb3.bean;
    
    import javax.persistence.Column;
    import javax.persistence.DiscriminatorValue;
    import javax.persistence.Entity;
    
    @Entity
    @DiscriminatorValue("Car")
    public class Car extends Vehicle{
    private static final long serialVersionUID = -8744304233821634737L;
    private String engine;//发动机
    
        @Column(nullable=true,length=30)
        public String getEngine() {
            return engine;
        }
    
        public void setEngine(String engine) {
            this.engine = engine;
        }
    }
    

    Camion.java (Camion 继承Car,并有自己的属性container)

    package com.foshanshop.ejb3.bean;
    
    import javax.persistence.Column;
    import javax.persistence.DiscriminatorValue;
    import javax.persistence.Entity;
    
    @Entity
    @DiscriminatorValue("Camion")
    public class Camion extends Car{
    private static final long serialVersionUID = -1266718346507357439L;
    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 约束,可见
    这种映
    射方式无法保证关系数据模型的数据完整性。

    EntityInheritanceDAOBean.java

    package com.foshanshop.ejb3.impl;
    
    import java.util.List;
    
    import javax.ejb.Remote;
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    
    import com.foshanshop.ejb3.EntityInheritanceDAO;
    import com.foshanshop.ejb3.bean.Car;
    import com.foshanshop.ejb3.bean.Vehicle;
    import com.foshanshop.ejb3.bean.Camion;
    
    @Stateless
    @Remote (EntityInheritanceDAO.class)
    public class EntityInheritanceDAOBean implements EntityInheritanceDAO {
        @PersistenceContext protected EntityManager em;
      
        public void initializeData(){
            //添加Vehicle
            Vehicle vehicle = new Vehicle();
                vehicle.setSpeed((short)100);
            em.persist(vehicle);
            //添加Car
            Car car = new Car();
                car.setSpeed((short)300);
                car.setEngine("A发动机");
            em.persist(car);
            //添加Camion
            Camion camion = new Camion();
                camion.setSpeed((short)200);
                camion.setEngine("B发动机");
                camion.setContainer("2吨集装箱");
            em.persist(camion);
        }
        
        @SuppressWarnings("unchecked")
    public List<Vehicle> getVehicle() { 
            //查询所有Vehicle时,因为它是最继承树中的根,查询结果会得到所有继承于Vehicle类的记录
            //转绎成的SQL片断:select * from Vehicle_Hierarchy      
            Query query = em.createQuery("select v from Vehicle v");
            return (List<Vehicle>)query.getResultList();
        } 
    
        @SuppressWarnings("unchecked")
        public List<Car> getCar() { 
            //查询所有Car时,除了得到Car类的记录,也会得到所有继承于Car类的记录
            //构造的SQL Where部分:where Discriminator in ('Car', 'Camion')
            Query query = em.createQuery("select c from Car c");
            return (List<Car>)query.getResultList();
        }
    
        @SuppressWarnings("unchecked")
        public List<Camion> getCamion() {        
            Query query = em.createQuery("select c from Camion c");
            return (List<Camion>)query.getResultList();
        }  
        
        public void deleteVehicle() {  
            //执行该操作会删除自身对应记录,还会删除所有继承Vehicle的记录,
            //因为它是最继承树中的根,就相当于清除整个表的数据
            Query query = em.createQuery("delete from Vehicle v");
            query.executeUpdate();
        }  
    }
    

    该策略的优点
    SINGLE_TABLE 映射策略在所有继承策略中是最简单的,同时也是执行效率最高的。他仅需对一个表进行管理及操作,持久化引掣在载入entiry 或多态连接时不需要进行任何的关联,联合或子查询,因为所有数据都存储在一个表。
    该策略的缺点
    这种策略最大的一个缺点是需要对关系数据模型进行非常规设计,在数据库表中加入额外的区分各个子类的字段,此外,不能为所有子类的属性对应的字段定义not null 约束,此策略的关系数据模型完全不支持对象的继承关系。
    选择原则:查询性能要求高,子类属性不是非常多时,优先选择该策略。

                                                                                                                                                                                            

    2  每个子类一张表(table per subclass)

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

    Vehicle.java

    package com.foshanshop.ejb3.bean;
    
    import java.io.Serializable;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Inheritance;
    import javax.persistence.InheritanceType;
    
    @Entity
    @Inheritance(strategy=InheritanceType.JOINED)
    public class Vehicle implements Serializable{
    private static final long serialVersionUID = -3196397365804550797L;
    private Long id;
        private Short speed;//速度
        
        @Id
        @GeneratedValue
        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;
        }
    }
    

    Car.java

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.PrimaryKeyJoinColumn;
    
    @Entity
    @PrimaryKeyJoinColumn(name="CarID")
    public class Car extends Vehicle{
    private static final long serialVersionUID = -8744304233821634737L;
    private String engine;//发动机
    
        @Column(nullable=true,length=30)
        public String getEngine() {
            return engine;
        }
    
        public void setEngine(String engine) {
            this.engine = engine;
        }
    }
    

    Camion .java

    package com.foshanshop.ejb3.bean;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.PrimaryKeyJoinColumn;
    
    @Entity
    @PrimaryKeyJoinColumn(name="CamionID")
    public class Camion extends Car{
    private static final long serialVersionUID = -1266718346507357439L;
    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 约束,且对性能要求不是很严格时,优先选择该策略。

                                                                                                                                                                                            

                                      3 每个具体类一张表(table per concrete class)

    这种映射方式为每个类创建一个表。在每个类对应的表中包含和这个类所有属性(包括从超类继承的属性)对应
    的字段。

    要使用每个具体类一张表(table per concrete class)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.TABLE_PER_CLASS。

    Vehicle.java

    package com.foshanshop.ejb3.bean;
    
    import java.io.Serializable;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Inheritance;
    import javax.persistence.InheritanceType;
    import javax.persistence.TableGenerator;
    
    @Entity
    @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
    public class Vehicle implements Serializable{
    private static final long serialVersionUID = -3196397365804550797L;
    private Long id;
        private Short speed;//速度
        
        @Id
       @TableGenerator(name="VehicleID_Generator",//为该生成方式取个名称
                table="VehicleID_Generator",//定义用于生成ID的表
                pkColumnName="PRIMARY_KEY_COLUMN",//主键字段的名称
                valueColumnName="VALUE_COLUMN",//存放生成ID值的字段
                pkColumnValue="vehicle",//主键字段的值(该值用于定位某条记录,然后累加其ID值)
                allocationSize=1 
                )
        @GeneratedValue(strategy=GenerationType.TABLE, generator="VehicleID_Generator")
        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;
        }    
    }
    

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

    Car.java

    package com.foshanshop.ejb3.bean;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    
    @Entity
    public class Car extends Vehicle{
    private static final long serialVersionUID = -8744304233821634737L;
    private String engine;//发动机
    
        @Column(nullable=true,length=30)
        public String getEngine() {
            return engine;
        }
    
        public void setEngine(String engine) {
            this.engine = engine;
        }    
    }
    

    Camion.java

    package com.foshanshop.ejb3.bean;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    
    @Entity
    public class Camion extends Car{
    private static final long serialVersionUID = -1266718346507357439L;
    private String container;//集装箱
    
        @Column(nullable=true,length=30)
        public String getContainer() {
            return container;
        }
    
        public void setContainer(String container) {
            this.container = container;
        }    
    }
    

    Session Bean

    package com.foshanshop.ejb3.impl;
    
    import java.util.List;
    
    import javax.ejb.Remote;
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.persistence.Query;
    
    import com.foshanshop.ejb3.EntityInheritanceDAO;
    import com.foshanshop.ejb3.bean.Car;
    import com.foshanshop.ejb3.bean.Vehicle;
    import com.foshanshop.ejb3.bean.Camion;
    
    @Stateless
    @Remote (EntityInheritanceDAO.class)
    public class EntityInheritanceDAOBean implements EntityInheritanceDAO {
        @PersistenceContext protected EntityManager em;
      
        public void initializeData(){
            //添加Vehicle
            Vehicle vehicle = new Vehicle();
                vehicle.setSpeed((short)100);
            em.persist(vehicle);
            //添加Car
            Car car = new Car();
                car.setSpeed((short)300);
                car.setEngine("A发动机");
            em.persist(car);
            //添加Camion
            Camion camion = new Camion();
                camion.setSpeed((short)200);
                camion.setEngine("B发动机");
                camion.setContainer("2吨集装箱");
            em.persist(camion);
        }
        
        @SuppressWarnings("unchecked")
    public List<Vehicle> getVehicle() { 
            //查询所有Vehicle时,因为它是最继承树中的根,查询结果会得到所有继承于Vehicle类的记录
            //转绎成的SQL片断:select * from Vehicle_Hierarchy      
            Query query = em.createQuery("select v from Vehicle v");
            return (List<Vehicle>)query.getResultList();
        } 
    
        @SuppressWarnings("unchecked")
        public List<Car> getCar() { 
            //查询所有Car时,除了得到Car类的记录,也会得到所有继承于Car类的记录
            //构造的SQL Where部分:where Discriminator in ('Car', 'Camion')
            Query query = em.createQuery("select c from Car c");
            return (List<Car>)query.getResultList();
        }
    
        @SuppressWarnings("unchecked")
        public List<Camion> getCamion() {        
            Query query = em.createQuery("select c from Camion c");
            return (List<Camion>)query.getResultList();
        }  
        
        public void deleteVehicle() {  
            //执行该操作会删除自身对应记录,还会删除所有继承Vehicle的记录,
            //因为它是最继承树中的根,就相当于清除整个表的数据
            Query query = em.createQuery("delete from Vehicle v");
            query.executeUpdate();
        }  
    }
    

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

  • 相关阅读:
    Golang 开发环境安装和配置
    多测师肖老师__接口测试之cms搭建(27.1)
    多测师肖老师__接口测试之fn+f12查看接口(27.2)
    认识wpf中binding类型
    认识wpf的事件
    Jquery对象与Dom对象
    AS3编程中的两种常用事件
    SQL Server 系统表简介
    Winform中ComcoBox控件设置选定项
    wpf开篇入门
  • 原文地址:https://www.cnblogs.com/xqzt/p/5637336.html
Copyright © 2020-2023  润新知