zoukankan      html  css  js  c++  java
  • 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 查询来实现这种策略。
    选择原则:除非你的现实情况必须使用这种策略,一般情况下不要选择。

  • 相关阅读:
    14.4.9 Configuring Spin Lock Polling 配置Spin lock 轮询:
    14.4.8 Configuring the InnoDB Master Thread IO Rate 配置InnoDB Master Thread I/O Rate
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.7 Configuring the Number of Background InnoDB IO Threads 配置 后台InnoDB IO Threads的数量
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.6 Configuring Thread Concurrency for InnoDB 配置Thread 并发
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.5 Configuring InnoDB Change Buffering 配置InnoDB Change Buffering
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
    14.4.4 Configuring the Memory Allocator for InnoDB InnoDB 配置内存分配器
  • 原文地址:https://www.cnblogs.com/xqzt/p/5637336.html
Copyright © 2011-2022 走看看