hibernate 映射继承关系

时间:2016-06-07 14:51:00 来源:互联网 作者: 神秘的大神 字体:

实现方式一般有三种: 1. 继承关系树每个具体类对应一张表(不介绍) 2. 继承关系树的根类对应一张表 3. 继承关系树的每个类对应一张表 先介绍关系: DayEmployee和MonthEmploy是Employee的子类,并且Company和Employee是一对多关系: 具体代码如下: Compan

实现方式一般有三种:
1. 继承关系树每个具体类对应一张表(不介绍)
2. 继承关系树的根类对应一张表
3. 继承关系树的每个类对应一张表

先介绍关系:
DayEmployee和MonthEmploy是Employee的子类,并且Company和Employee是一对多关系:

具体代码如下:

Company.java

import java.util.HashSet;
import java.util.Set;

public class Company {
    private Integer id;
    private String name;
    private Set
  
    employees = 
   new HashSet
   
    (); 
    public 
    Company() { 
    super(); } 
    public 
    Company(String name) { 
    super(); 
    this.name = name; } 
    public Integer 
    getId() { 
    return id; } 
    public 
    void 
    setId(Integer id) { 
    this.id = id; } 
    public String 
    getName() { 
    return name; } 
    public 
    void 
    setName(String name) { 
    this.name = name; } 
    public Set
     
     getEmployees() { 
     return employees; } 
     public 
     void 
     setEmployees(Set
     
       employees) { 
      this.employees = employees; } }
     
    
   
  

Employee.java

    public class Employee {
    private Integer id;
    private String name;
    private Integer age;
    private Company company;
    public Company getCompany() {
        return company;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }

}

DayEmployee.java

public class DayEmployee extends Employee{
    private Double dayMoney;

    public Double getDayMoney() {
        return dayMoney;
    }
    public void setDayMoney(Double dayMoney) {
        this.dayMoney = dayMoney;
    }

}

MonthEmploy.java

    public class MonthEmploy extends Employee{
    private Double monthMoney;

    public Double getMonthMoney() {
        return monthMoney;
    }
    public void setMonthMoney(Double monthMoney) {
        this.monthMoney = monthMoney;
    }

}

Company.hbm.xml


   

<hibernate-mapping package="com.dongecs.test1.pojo">
    <class name="Company" table="COMPANY">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        
   id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        
   property>
        <set name="employees" table="EMPLOYEE" inverse="true" lazy="true">
            <key>
                <column name="COMPANY" />
            
   key>
            <one-to-many class="Employee" />
        
   set>
    
   class>

   hibernate-mapping>

继承关系树的根类对应一张表对应的Employee.hbm.xml的写法

Employee.hbm.xml


   

<hibernate-mapping package="com.dongecs.test1.pojo">
    
   
    <class name="Employee" table="EMPLOYEE" discriminator-value="emp">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        
   id>
       
   
        <discriminator column="empType" type="string"/>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        
   property>
        <property name="age" type="java.lang.Integer">
            <column name="AGE" />
        
   property>
        <many-to-one name="company" class="Company" fetch="join">
            <column name="COMPANY" />
        
   many-to-one>
       
   
        <subclass name="DayEmployee" discriminator-value="DE">
            <property name="dayMoney" type="double">
   property>
        
   subclass>
         
   
        <subclass name="MonthEmploy" discriminator-value="ME">
            <property name="monthMoney" type="double">
   property>
        
   subclass>
    
   class>

   hibernate-mapping>

利用上述代码作如下测试:

public class EmployeeTest {

    SessionFactory sessionFactory = null;
    Session session = null;
    Transaction transaction = null;

    @Before
    public void init() {
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void after() {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }

    @Test
    public void testEmployee() {
        Company company = new Company("com1");

        DayEmployee d1 = new DayEmployee();
        d1.setAge(22);
        d1.setDayMoney(50.0);
        d1.setName("d1");

        MonthEmploy d2 = new MonthEmploy();
        d2.setAge(30);
        d2.setMonthMoney(79.0);
        d2.setName("d2");

        Employee employee = new Employee();
        employee.setAge(90);
        employee.setName("employee");

        d1.setCompany(company);
        d2.setCompany(company);
        employee.setCompany(company);

        //inverse = true 时可以关联, 当相对多出3条update,因此建议使用多的一端关联
// company.getEmployees().add(employee);
// company.getEmployees().add(d1);
// company.getEmployees().add(d2);

        //把一的一段放到最前保存,可以减小3条更新操作
        session.save(company);

        session.save(employee);
        session.save(d2);
        session.save(d1);
    }
}

会得出如下结果:
这里写图片描述

继承关系树的每个类对应一张表Employee.hbm.xml的写法


   

<hibernate-mapping package="com.dongecs.test1.pojo">
    <class name="Employee" table="EMPLOYEE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        
   id>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        
   property>
        <property name="age" type="java.lang.Integer">
            <column name="AGE" />
        
   property>
        <many-to-one name="company" class="Company" fetch="join">
            <column name="COMPANY" />
        
   many-to-one>
        
   
        <joined-subclass name="MonthEmploy" table="MONEMPLOY">
            <key column="EMPLOYEE_ID">
   key>
            <property name="monthMoney" type="double">
   property>
        
   joined-subclass>
        <joined-subclass name="DayEmployee" table="DAYEMPLOY">
            <key column="EMPLOYEE_ID">
   key>
            <property name="dayMoney" type="double">
   property>
        
   joined-subclass>
    
   class>

   hibernate-mapping>

测试代码:

public class EmployeeTest {

    SessionFactory sessionFactory = null;
    Session session = null;
    Transaction transaction = null;

    @Before
    public void init() {
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties())
                .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @After
    public void after() {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }

    @Test
    public void testEmployee() {
        Company company = new Company("com1");

        DayEmployee d1 = new DayEmployee();
        d1.setAge(22);
        d1.setDayMoney(50.0);
        d1.setName("d1");

        MonthEmploy d2 = new MonthEmploy();
        d2.setAge(30);
        d2.setMonthMoney(79.0);
        d2.setName("d2");

        Employee employee = new Employee();
        employee.setAge(90);
        employee.setName("employee");

        d1.setCompany(company);
        d2.setCompany(company);
        employee.setCompany(company);

        //inverse = true 时可以关联, 当相对多出3条update,因此建议使用多的一端关联
// company.getEmployees().add(employee);
// company.getEmployees().add(d1);
// company.getEmployees().add(d2);

        //把一的一段放到最前保存,可以减小3条更新操作
        session.save(company);

        session.save(employee);
        session.save(d2);
        session.save(d1);
    }

    @Test
    public void findFromEmployeeTable(){
        String hql = "from Employee";
        //通过左外链接找
        List
  
    list = session.createQuery(hql).list(); 
   for (Employee emp : list){ 
   if (emp 
   instanceof DayEmployee){ System.out.println(
   "day"); } 
   else 
   if (emp 
   instanceof MonthEmploy){ System.out.println(
   "mon"); } 
   else { System.out.println(
   "emp"); } } } 
   @Test 
   public 
   void 
   findFromDayEmployeeTable(){ String hql = 
   "from DayEmployee"; 
   //通过内连接找 List
   
     list = session.createQuery(hql).list(); System.out.println(list.size()); } } 
   
  

得出如下结果:
这里写图片描述
这里写图片描述

结论:

1.使用根类对应一张表
好处:只需创建一张表,不用外键关联
缺点:如果子类属性多,会导致另一子类有过多的空值,而且不能设置一些字段的not null约束,因此不能保证数据库的完整性
2.每个类对应一张表(外键关联)
好处:如果某个类的属性发生变化,只需修改和这个类对应的表
缺点:利用外键关联查询

ref:

孙卫琴.精通Hibernate:Java对象持久化技术详解