Hibernate(20)Hibernate如何处理继承关系?

Hibernate提供了几种策略来处理继承关系,主要有三种:

  1. 单表继承(Single Table Inheritance):在单个表中存储继承层次结构的所有类。
  2. 表连接继承(Joined Table Inheritance):为每个类创建独立的表,并使用外键建立关联。
  3. 表每类继承(Table Per Class Inheritance):为每个具体类创建独立的表,不存储父类信息。

下面详细介绍这三种策略,并通过具体的示例代码演示如何在Hibernate中实现它们。

单表继承(Single Table Inheritance)

在单表继承策略中,继承层次结构的所有类的属性和数据都存储在同一个表中,通过一个区分列(discriminator column)来区分具体的类型。

示例

配置文件 hibernate.cfg.xml
xml 复制代码
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
        <property name="hibernate.connection.username">your_username</property>
        <property name="hibernate.connection.password">your_password</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <mapping class="com.example.domain.Person"/>
        <mapping class="com.example.domain.Employee"/>
        <mapping class="com.example.domain.Student"/>
    </session-factory>
</hibernate-configuration>
实体类
父类 Person
java 复制代码
package com.example.domain;

import javax.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "person_type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;

    // constructors, getters, and setters
    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
子类 Employee
java 复制代码
package com.example.domain;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("EMPLOYEE")
public class Employee extends Person {
    private double salary;

    // constructors, getters, and setters
    public Employee() {}

    public Employee(String name, double salary) {
        super(name);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
子类 Student
java 复制代码
package com.example.domain;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@DiscriminatorValue("STUDENT")
public class Student extends Person {
    private String major;

    // constructors, getters, and setters
    public Student() {}

    public Student(String name, String major) {
        super(name);
        this.major = major;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }
}

插入和查询示例代码

java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class HibernateSingleTableInheritanceExample {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        // 插入数据
        insertSampleData(sessionFactory);

        // 查询数据
        queryData(sessionFactory);

        // 关闭SessionFactory
        sessionFactory.close();
    }

    private static void insertSampleData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try {
            Employee employee = new Employee("John Doe", 50000.0);
            Student student = new Student("Jane Doe", "Computer Science");

            session.save(employee);
            session.save(student);

            transaction.commit();
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    private static void queryData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        try {
            List<Person> persons = session.createQuery("FROM Person", Person.class).list();
            for (Person person : persons) {
                System.out.println("Person: " + person.getName());
                if (person instanceof Employee) {
                    System.out.println("Employee Salary: " + ((Employee) person).getSalary());
                } else if (person instanceof Student) {
                    System.out.println("Student Major: " + ((Student) person).getMajor());
                }
            }
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

表连接继承(Joined Table Inheritance)

在表连接继承策略中,为每个类创建独立的表,子类表包含自己的属性并通过外键引用父类表中的记录。

示例

实体类
父类 Person
java 复制代码
package com.example.domain;

import javax.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;

    // constructors, getters, and setters
    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
子类 Employee
java 复制代码
package com.example.domain;

import javax.persistence.Entity;

@Entity
public class Employee extends Person {
    private double salary;

    // constructors, getters, and setters
    public Employee() {}

    public Employee(String name, double salary) {
        super(name);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
子类 Student
java 复制代码
package com.example.domain;

import javax.persistence.Entity;

@Entity
public class Student extends Person {
    private String major;

    // constructors, getters, and setters
    public Student() {}

    public Student(String name, String major) {
        super(name);
        this.major = major;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }
}

查询和插入数据的代码与单表继承的示例相同。

表每类继承(Table Per Class Inheritance)

在表每类继承策略中,每个具体类都有自己的独立表,不存储父类信息,所有字段(包括父类的字段)都在子类表中。

示例

实体类
父类 Person
java 复制代码
package com.example.domain;

import javax.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;
    
    private String name;

    // constructors, getters, and setters
    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
子类 Employee
java 复制代码
package com.example.domain;

import javax.persistence.Entity;

@Entity
public class Employee extends Person {
    private double salary;

    // constructors, getters, and setters
    public Employee() {}

    public Employee(String name, double salary) {
        super(name);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}
子类 Student
java 复制代码
package com.example.domain;

import javax.persistence.Entity;

@Entity
public class Student extends Person {
    private String major;

    // constructors, getters, and setters
    public Student() {}

    public Student(String name, String major) {
        super(name);
        this.major = major;
    }

    public String getMajor() {
        return major;
    }

    
相关推荐
咚为7 小时前
Rust Print 终极指南:从底层原理到全场景实战
开发语言·后端·rust
二哈喇子!7 小时前
基于Spring Boot框架的车库停车管理系统的设计与实现
java·spring boot·后端·计算机毕业设计
Loo国昌10 小时前
【LangChain1.0】第九阶段:文档处理工程 (LlamaIndex)
人工智能·后端·python·算法·langchain
毕设源码-朱学姐10 小时前
【开题答辩全过程】以 基于SpringBoot的律师事务所管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
愈努力俞幸运11 小时前
flask 入门 token, headers,cookie
后端·python·flask
毕设源码-朱学姐11 小时前
【开题答辩全过程】以 基于springboot的日用药品仓库管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
lkbhua莱克瓦2412 小时前
深入理解HTTP协议:从理论到SpringBoot实践
网络·笔记·后端·网络协议·http·javaweb
古城小栈13 小时前
Rust复合类型 四大军阀:数、元、切、串
开发语言·后端·rust
+VX:Fegn089514 小时前
计算机毕业设计|基于springboot + vue酒店预订系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
JavaGuide15 小时前
IntelliJ IDEA 2026.1 EAP 发布!拥抱 Java 26,Spring Boot 4 深度支持!
java·后端·mysql·springboot·idea·大厂面试·javaguide