《Hibernate上课笔记》----class4----Hibernate继承关系映射实现详解

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 《Hibernate上课笔记》----class4----Hibernate继承关系映射实现详解

一:需求分析

  • 现要为某公司开发一个员工信息管理系统,已经了解到该公司的员工中有按小时记薪和按月记薪两种方式,这种情况下系统中该如何维护员工的基本信息呢?
  • 包含域模型设计:

20210321175427321.png

  • 因为域模型就有一种,所以每种方式的域模型都是一样的,只是数据库关系不一样。

二:每个具体类对应一张表(Table per concrete class)

  • 数据库创建时,按时薪计算的员工创建一张表,按月薪计算的员工创建一张表。

时薪员工数据表结构:


20210321175835601.png

月薪员工数据表结构:

20210321175900790.png

1.使用xml的方式配置

员工类:


public class Employee {
  private Integer id;
  private String name;
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + "]";
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

时薪员工类:

public class HourlyEmployee extends Employee {
  private double rate;
  public double getRate() {
    return rate;
  }
  public void setRate(double rate) {
    this.rate = rate;
  }
  @Override
  public String toString() {
    return "HourlyEmployee [rate=" + rate + ", getId()=" + getId() + ", toString()=" + super.toString()
        + ", getName()=" + getName() + "]";
  }
}

时薪员工类xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.entity">
  <class name="HourlyEmployee" table="hourly_employee">
    <id name="id" type="int">
      <column name="id"></column>
      <generator class="native"></generator>
    </id>
    <property name="name" type="java.lang.String">
    </property>
    <property name="rate" type="double" />
  </class>
</hibernate-mapping>

月薪员工类:

public class SalariedEmployee extends Employee {
  private double salay;
  public double getSalay() {
    return salay;
  }
  public void setSalay(double salay) {
    this.salay = salay;
  }
  @Override
  public String toString() {
    return "SalariedEmployee [salay=" + salay + ", toString()=" + super.toString() + "]";
  }
}

月薪员工类xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.entity">
  <class name="SalariedEmployee" table="salaied_employee">
    <id name="id" type="int">
      <column name="id"></column>
      <generator class="increment"></generator>
    </id>
    <property name="name" type="java.lang.String">
    </property>
    <property name="salay" type="double" column="salary"></property>
  </class>
</hibernate-mapping>

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test1?useUnicode=true&amp;characterEncoding=UTF-8</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.format_sql">true</property>
    <mapping resource="com/hibernate/entity/HourlyEmployee.hbm.xml" />
    <mapping resource="com/hibernate/entity/SalariedEmployee.hbm.xml" />
  </session-factory>
</hibernate-configuration>

测试类:

public class Test {
  public static void main(String[] args) {
    // 1.测试员工是否能成功入库
    HourlyEmployee hourlyEmployee = new HourlyEmployee();
    hourlyEmployee.setName("20");
    hourlyEmployee.setRate(50);
    SalariedEmployee salariedEmployee = new SalariedEmployee();
    salariedEmployee.setName("888");
    salariedEmployee.setSalay(30);
    // 保存按小时记新员工信息
    // saveEmployee(salariedEmployee);
    findEmployee();
  }
  private static void saveEmployee(Employee e) {
    // 1.获取session
    Session session = HibernateUtil.openSession();
    Transaction tx = session.beginTransaction();
    session.save(e);
    tx.commit();
    // 关闭session
    session.close();
  }
  private static void findEmployee() {
    // 1.获取session
    Session session = HibernateUtil.openSession();
    Transaction tx = session.beginTransaction();
    HourlyEmployee he = session.get(HourlyEmployee.class, new Integer(1));
    System.out.println(he);
    SalariedEmployee se = session.get(SalariedEmployee.class, new Integer(1));
    System.out.println(se);
  }
}

2.使用注解的方式配置

员工类:

@MappedSuperclass
public class Employee {
  private Integer id;
  private String name;
  @Id
  @GeneratedValue(generator = "my_increment")
  @GenericGenerator(name = "my_increment", strategy = "native")
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + "]";
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

时薪员工类:

@Entity
@Table(name = "hourly_employee")
public class HourlyEmployee extends Employee {
  private double rate;
  public double getRate() {
    return rate;
  }
  public void setRate(double rate) {
    this.rate = rate;
  }
  @Override
  public String toString() {
    return "HourlyEmployee [rate=" + rate + ", getId()=" + getId() + ", toString()=" + super.toString()
        + ", getName()=" + getName() + "]";
  }
}

月薪员工类:

@Entity
@Table(name = "salaied_employee")
public class SalariedEmployee extends Employee {
  private double salay;
  @Column(name = "salary")
  public double getSalay() {
    return salay;
  }
  public void setSalay(double salay) {
    this.salay = salay;
  }
  @Override
  public String toString() {
    return "SalariedEmployee [salay=" + salay + ", toString()=" + super.toString() + "]";
  }
}

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test1?useUnicode=true&amp;characterEncoding=UTF-8</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.format_sql">true</property>
    <mapping class="com.hibernate.entity.Employee" />
    <mapping class="com.hibernate.entity.HourlyEmployee" />
    <mapping class="com.hibernate.entity.SalariedEmployee" />
  </session-factory>
</hibernate-configuration>

测试类:

public class Test {
  public static void main(String[] args) {
    // 1.测试员工是否能成功入库
    HourlyEmployee hourlyEmployee = new HourlyEmployee();
    hourlyEmployee.setName("20");
    hourlyEmployee.setRate(50);
    SalariedEmployee salariedEmployee = new SalariedEmployee();
    salariedEmployee.setName("888");
    salariedEmployee.setSalay(30);
    // 保存按小时记新员工信息
    // saveEmployee(salariedEmployee);
    findEmployee();
  }
  private static void saveEmployee(Employee e) {
    // 1.获取session
    Session session = HibernateUtil.openSession();
    Transaction tx = session.beginTransaction();
    session.save(e);
    tx.commit();
    // 关闭session
    session.close();
  }
  private static void findEmployee() {
    // 1.获取session
    Session session = HibernateUtil.openSession();
    Transaction tx = session.beginTransaction();
    HourlyEmployee he = session.get(HourlyEmployee.class, new Integer(1));
    System.out.println(he);
    SalariedEmployee se = session.get(SalariedEmployee.class, new Integer(1));
    System.out.println(se);
  }
}

三:父类对应一个表(Table per class hierarchy)

父类创建一个表,每个子类的字段都包含,再增加一个字段用来区别每个子类的类型。

数据表结构:


20210321193753281.png

持久化类、映射文件和数据库表之间的关系:

20210321193927816.png

1.使用xml的方式配置

员工类,时薪员工类,月薪员工类同上。

员工类配置文件:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.entity">
  <class name="Employee" table="employee">
    <id name="id" type="int">
      <column name="id"></column>
      <generator class="native"></generator>
    </id>
    <discriminator column="employee_type"></discriminator>
    <property name="name" type="java.lang.String">
    </property>
    <subclass name="HourlyEmployee" discriminator-value="HE">
      <property name="rate"></property>
    </subclass>
    <subclass name="SalariedEmployee" discriminator-value="SE">
      <property name="salay"></property>
    </subclass>
  </class>
</hibernate-mapping>

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test1?useUnicode=true&amp;characterEncoding=UTF-8</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.format_sql">true</property>
    <mapping resource="com/hibernate/entity/Employee.hbm.xml" />
  </session-factory>
</hibernate-configuration>

2.使用注解的方式配置

员工类:


@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee_type")
public class Employee {
  private Integer id;
  private String name;
  @Id
  @GeneratedValue(generator = "my_increment")
  @GenericGenerator(name = "my_increment", strategy = "native")
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + "]";
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

时薪员工类:

@Entity
@DiscriminatorValue(value = "HE")
public class HourlyEmployee extends Employee {
  private double rate;
  public double getRate() {
    return rate;
  }
  public void setRate(double rate) {
    this.rate = rate;
  }
  @Override
  public String toString() {
    return "HourlyEmployee [rate=" + rate + ", getId()=" + getId() + ", toString()=" + super.toString()
        + ", getName()=" + getName() + "]";
  }
}

月薪员工类:

@Entity
@DiscriminatorValue(value = "SE")
public class SalariedEmployee extends Employee {
  private double salay;
  @Column(name = "salary")
  public double getSalay() {
    return salay;
  }
  public void setSalay(double salay) {
    this.salay = salay;
  }
  @Override
  public String toString() {
    return "SalariedEmployee [salay=" + salay + ", toString()=" + super.toString() + "]";
  }
}

hibernate.cfg.xml:

@Entity
@DiscriminatorValue(value = "SE")
public class SalariedEmployee extends Employee {
  private double salay;
  @Column(name = "salary")
  public double getSalay() {
    return salay;
  }
  public void setSalay(double salay) {
    this.salay = salay;
  }
  @Override
  public String toString() {
    return "SalariedEmployee [salay=" + salay + ", toString()=" + super.toString() + "]";
  }
}

四:每个类对应一个表(Table per class)

父类,子类都分别对应一张表,父类中包含共有的字段,子类用外键参照关系来表示继承关系。

数据表结构:

20210321202953345.png

持久化类,数据库文件,映射表之间的关系:

20210321203038114.png

加粗样式

1.使用xml的方式进行配置

配置文件:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hibernate.entity">
  <class name="Employee" table="employee1">
    <id name="id" type="int">
      <column name="id"></column>
      <generator class="native"></generator>
    </id>
    <property name="name"></property>
    <joined-subclass name="HourlyEmployee"
      table="hourly_employee1">
      <key column="id"></key>
      <property name="rate"></property>
    </joined-subclass>
    <joined-subclass name="SalariedEmployee"
      table="salaried_employee1">
      <key column="id"></key>
      <property name="salay" column="salary"></property>
    </joined-subclass>
  </class>
</hibernate-mapping>

2.使用注解的方式配置

员工类:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Employee {
  private Integer id;
  private String name;
  @Id
  @GeneratedValue(generator = "my_increment")
  @GenericGenerator(name = "my_increment", strategy = "native")
  public Integer getId() {
    return id;
  }
  public void setId(Integer id) {
    this.id = id;
  }
  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + "]";
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}

时薪员工类:

@Entity
@Table(name="hourly_employee1")
@PrimaryKeyJoinColumn(name="id")
public class HourlyEmployee extends Employee {
  private double rate;
  public double getRate() {
    return rate;
  }
  public void setRate(double rate) {
    this.rate = rate;
  }
  @Override
  public String toString() {
    return "HourlyEmployee [rate=" + rate + ", getId()=" + getId() + ", toString()=" + super.toString()
        + ", getName()=" + getName() + "]";
  }
}

月薪员工类:

@Entity
@Table(name="salaried_employee1")
@PrimaryKeyJoinColumn(name="id")
public class SalariedEmployee extends Employee {
  private double salay;
  @Column(name = "salary")
  public double getSalay() {
    return salay;
  }
  public void setSalay(double salay) {
    this.salay = salay;
  }
  @Override
  public String toString() {
    return "SalariedEmployee [salay=" + salay + ", toString()=" + super.toString() + "]";
  }
}
相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
3月前
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
65 4
|
4月前
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
92 0
|
4月前
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
55 0
|
7月前
|
SQL Java 关系型数据库
Hibernate - 对象关系映射文件(*.hbm.xml)详解
Hibernate - 对象关系映射文件(*.hbm.xml)详解
303 1
|
7月前
|
缓存 Java 数据库连接
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
134 0
|
7月前
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
143 0
|
7月前
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
75 0
|
7月前
|
机器学习/深度学习 SQL Java
Hibernate - 多对多关联关系映射
Hibernate - 多对多关联关系映射
71 0
|
7月前
|
SQL Java 数据库连接
Hibernate -双向一对一关联关系映射
Hibernate -双向一对一关联关系映射
57 0
|
7月前
|
SQL XML Java
Hibernate - 单向多对一关联关系映射
Hibernate - 单向多对一关联关系映射
42 0