hibernate 映射继承关系

实现方式一般有三种:

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<Employee> employees = new HashSet<Employee>();

    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<Employee> getEmployees() {
        return employees;
    }
    public void setEmployees(Set<Employee> 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

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<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

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.dongecs.test1.pojo">
    <!-- 利用discriminator-value默认 empType 的值为emp -->
    <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>
       <!--  若为DayEmployee,那么将empType的值设为DE -->
        <subclass name="DayEmployee" discriminator-value="DE">
            <property name="dayMoney" type="double"></property>
        </subclass>
         <!--  若为MonthEmploy,那么将empType的值设为ME -->
        <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的写法

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<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表签外键关联MonthEmploy -->
        <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<Employee> 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<Employee> list = session.createQuery(hql).list();
        System.out.println(list.size());
    }
}

得出如下结果:

结论:

1.使用根类对应一张表

好处:只需创建一张表,不用外键关联

缺点:如果子类属性多,会导致另一子类有过多的空值,而且不能设置一些字段的not null约束,因此不能保证数据库的完整性

2.每个类对应一张表(外键关联)

好处:如果某个类的属性发生变化,只需修改和这个类对应的表

缺点:利用外键关联查询

ref:

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

时间: 2024-10-10 18:14:55

hibernate 映射继承关系的相关文章

hibernate 映射组成关系

建立域模型和关系数据模型有着不同的出发点: 域模型: 由程序代码组成, 通过细化持久化类的的粒度可提高代码的可重用性, 简化编程 在没有数据冗余的情况下, 应该尽可能减少表的数目, 简化表之间的参照关系, 以便提高数据的访问速度 Hibernate 把持久化类的属性分为两种: 值(value)类型: 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期 实体(entity)类型: 有 OID, 可以被单独持久化, 有独立的生命周期(如果实体类型包含值类型,这个值类型就

[原创]java WEB学习笔记87:Hibernate学习之路-- -映射 继承关系(subclass , joined-subclass,union-subclass )

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Entity Framework Code First 映射继承关系

转载 http://www.th7.cn/Program/net/201301/122153.shtml Code First如何处理类之间的继承关系.Entity Framework Code First有三种处理类之间继承关系的方法,我们将逐一介绍这三种处理方法. 1.Table Per Hierarchy(TPH): 只建立一个表,把基类和子类中的所有属性都映射为表中的列. 2.Table Per Type(TPT): 为基类和每个子类建立一个表,每个与子类对应的表中只包含子类特有的属性对

Hibernate逍遥游记-第10章 映射继承关系-002继承关系树中的根类对应一个表(discriminator、subclass)

1. 2. 1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping 3 PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 7 &l

hibernate注解映射继承关系

数据库表 用户表(User) id username password 客户表(Customer),客户表id引用用户表id id phone 员工表(Employee),员工表id引用用户表id id qq 飞机表(Plane),飞机表包含客机和战斗机,客机有厕所,战斗机有武器 id type speed wc_position weapon_position 实体映射 //子类共享属性id,version @MappedSuperclass public abstract class Ide

javaEE 用户、部门、角色、权限实体的关系设计与hibernate映射配置文件关系总结

文章中的项目文件已经放到Github上,欢迎大家Follow,star, 地址:https://github.com/lawlite19/SmartEducation 一:设计实体,我这里通过uml设计,然后直接可以生成java实体类(方便查看各个类的关系) (1)用户登录类User与用户详细信息类UserDetails为一对一关系: (2)用户详细信息类UserDetails与部门为多对一关系:(一个部门有多个用户) (3)部门类是自关联的,有上级部门: (3)用户详细类UserDetails

hibernate映射组成关系

目录结构 类 package com.hibernate.helloworld; public class School { private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; }

精通Hibernate——映射组成关系

建立域模型与关系型数据模型有着不同的出发点.域模型是由程序代码组成,通过细化持久化类的粒度提供代码可重用度,简化编程.关系数据模型由关系数据组成.存在数据冗余的情况下,需要把粗粒度的表拆分为具有外键参照关系的几个细粒度表,从而节省表的存储空间:另一方面在没有数据冗余的前提下,应尽可能减少表的数量,简化表之间的参照关系,以便提高数据库的访问速度. 由于建立域模型和关系型数据的原则不一样,使得持久化类的数目往往比数据库中表的数量要多,而且持久化类的属性并不和表字段一一对应,下面Customer类的h

(七)Hibernate 映射继承

所有项目导入对应的hibernate的jar包.mysql的jar包和添加每次都需要用到的HibernateUtil.java 第一节:每个具体类对应一个表 Image.java 1 package com.wishwzp.model; 2 3 public abstract class Image { 4 5 private int id; 6 private String imageName; 7 private Student student; 8 9 public int getId()