Hibernate – 使用注释的每个层次结构的表
Hibernate是一个提供一些抽象层的框架,这意味着程序员不必担心实现,它会在内部为您完成实现,例如编写查询以执行CRUD操作、建立与数据库的连接等。开源、非侵入性、轻量级Java ORM(对象关系映射)框架,用于开发独立于数据库软件的持久性逻辑。
当对象保存在数据库中时,Hibernate 能够将对象的继承属性及其新属性存储在其数据库中。在 Hibernate 中,当一个模块的多个 POJO 类包含一些公共属性时,会应用POJO类之间的继承。
Hibernate 继承映射
面向对象可以对“是一个”和“有一个”关系进行建模。关系模型仅支持两个实体之间的“具有”关系。 Hibernate 有助于将此类对象与关系表进行映射。 Hibernate 中定义了三种继承映射策略。
- 每个层次结构的表
- 每个混凝土类的表
- 每个子类的表
每个层次结构的表(使用注释)
Table per Hierarchy是 hibernate 中的继承策略之一。在此策略中,整个层次结构映射到单个表。层次结构中所有类的所有属性都存储在一个表中。
在每个层次结构策略的表中:
- 数据库中只创建了一张表,用于存储整个类层次结构的数据。
- Hibernate 需要在表中添加一个称为鉴别器列的列,用于放置或存储子类对象的鉴别器值。
- 鉴别器列是强制性的,而在上面提到的其他两种映射策略中是可选的。
鉴别器唯一地标识类层次结构的基本类型。
重要注释
注释一: @Inheritance
该注释定义了用于实体类层次结构的继承策略。它在作为实体类层次结构根的实体类上指定。如果没有指定@Inheritance 注解或者没有为实体类层次结构指定继承,则使用SINGLE_TABLE映射策略。
语法: @继承
@Entity
@Table("name = students")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// Class
public class Student {
// Insert code here
}
注释 2: @DiscriminatorColumn
此注解用于定义 SINGLE_TABLE 和 JOINED 继承映射策略的鉴别器列。策略和鉴别器列仅在应用了不同继承策略的实体类层次结构或子层次结构的根中指定。如果未指定 @DiscriminatorColumn 注释,并且需要鉴别器列,则在这种情况下,鉴别器列的名称设置为其默认值“DTYPE” ,鉴别器类型设置为DiscriminatorType.STRING 。
@Entity
@Table("name = students")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "student", discriminatorType = DiscriminatorType.STRING)
// Class
public class Student {
// Insert code here
}
注释 3: @DiscriminatorValue
此注释用于为给定类型的实体设置鉴别器列的值。它只能在具体实体类上指定。如果未提及 @DiscriminatorValue 注释并且使用了鉴别器列,则将使用特定于提供程序的函数来生成表示实体类型的值。如果DiscriminatorType指定为STRING ,则默认的鉴别器值是实体本身的名称。继承策略和鉴别器列仅在应用了不同继承策略的实体类层次结构或子层次结构的根中指定。最佳实践是为层次结构中的每个实体类指定鉴别器值。
@Entity
@Table("name = employees")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "employee", discriminatorType = DiscriminatorType.STRING)
// Class
public class Employee{
// Insert code here
}
@Entity
@DiscriminatorValue(value = "ceo")
// Class
public class Ceo extends Employee {
// Insert code here
}
按层次结构实现表(使用注释)
在此示例中,我们将创建三个持久性类,其中Employee作为父类, P_Employee和C_Employee作为两个子类。
现在在这种方法中,整个层次结构映射到一个表。层次结构中所有类的所有属性都存储在一个表中。
创建数据库表以保持类层次结构
CREATE TABLE `Employee` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '0',
`age` BIGINT(3) NOT NULL DEFAULT '0',
`salary` BIGINT(11) NULL DEFAULT NULL,
`hourlyrate` BIGINT(11) NULL DEFAULT NULL,
`duration` BIGINT(11) NULL DEFAULT NULL,
`discriminator` VARCHAR(20) NOT NULL,
PRIMARY KEY (`id`)
)
Employee 表将存储所有三个类Employee、P_Employee 和 C_Employee的对象。
项目结构(IntelliJ IDEA):
为上述层次结构创建 Employee、P_Employee 和 C_Employee 类:
下面是Employee的实现。 Java文件:
Java
package com.exploit.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
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.Table;
@Entity
@Table(name = "Employee")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type",
discriminatorType
= DiscriminatorType.STRING)
@DiscriminatorValue(value = "EMP")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
@Column(name = "name") private String name;
@Column(name = "age") private int age;
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
Java
package com.exploit.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "PEMP")
public class P_Employee extends Employee {
@Column(name = "salary") private double salary;
public double getSalary() { return salary; }
public void setSalary(double salary)
{
this.salary = salary;
}
}
Java
package com.exploit.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "CEMP")
public class C_Employee extends Employee {
@Column(name = "hourlyRate") private double hourlyRate;
@Column(name = "duration") private double duration;
public double getDuration() { return duration; }
public void setDuration(double duration)
{
this.duration = duration;
}
public double getHourlyRate() { return hourlyRate; }
public void setHourlyRate(double hourlyRate)
{
this.hourlyRate = hourlyRate;
}
}
XML
com.mysql.jdbc.Driver
jdbc:mysql://localhost/heistmvr
root
root
100
org.hibernate.dialect.MySQLDialect
org.hibernate.cache.internal.NoCacheProvider
true
true
update
XML
4.0.0
TablePerHierarchyAnnotation
TablePerHierarchyAnnotation
0.0.1-SNAPSHOT
jar
TablePerHierarchyAnnotation
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
org.hibernate
hibernate-core
5.2.6.Final
mysql
mysql-connector-java
6.0.5
org.hibernate
hibernate-annotations
3.5.6-Final
Java
package com.exploit.db;
import com.exploit.model.C_Employee;
import com.exploit.model.Employee;
import com.exploit.model.P_Employee;
import com.exploit.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class Main {
public static void main(String[] args)
{
// Get session factory using Hibernate Util class
SessionFactory sessionFactory
= HibernateUtil.getSessionFactory();
// Get session from Sesson factory
Session session = sessionFactory.openSession();
// Begin transaction
Transaction transaction
= session.beginTransaction();
// Creating Employee base class record
Employee employee = new Employee();
employee.setName("KirikoChan");
employee.setAge(19);
// Creating Permanent Employee subclass record
P_Employee permanentEmployee = new P_Employee();
permanentEmployee.setName("Saili.H");
permanentEmployee.setAge(20);
permanentEmployee.setSalary(30000);
// Creating Contract Employee subclass record
C_Employee contractEmployee = new C_Employee();
contractEmployee.setName("ChikkoRita");
contractEmployee.setAge(21);
contractEmployee.setHourlyRate(2000);
contractEmployee.setDuration(7.5);
// persist all the employee records
session.persist(employee);
session.persist(permanentEmployee);
session.persist(contractEmployee);
// Commit the transaction and close the session
transaction.commit();
session.close();
System.out.println(
"Employee records successfully persisted.");
}
}
下面是P_Employee 的实现。 Java文件:
Java
package com.exploit.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "PEMP")
public class P_Employee extends Employee {
@Column(name = "salary") private double salary;
public double getSalary() { return salary; }
public void setSalary(double salary)
{
this.salary = salary;
}
}
下面是C_Employee 的实现。 Java文件:
Java
package com.exploit.model;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue(value = "CEMP")
public class C_Employee extends Employee {
@Column(name = "hourlyRate") private double hourlyRate;
@Column(name = "duration") private double duration;
public double getDuration() { return duration; }
public void setDuration(double duration)
{
this.duration = duration;
}
public double getHourlyRate() { return hourlyRate; }
public void setHourlyRate(double hourlyRate)
{
this.hourlyRate = hourlyRate;
}
}
我们将鉴别器定义为:
- “EMP”将保留在属于Employee类的鉴别器列中。
- “PEMP”将保留在属于P_Employee类的鉴别器列中。
- “CEMP”将保留在属于C_Employee类的鉴别器列中。
创建 hibernate.cgf.xml 配置文件并添加映射资源的条目:
XML
com.mysql.jdbc.Driver
jdbc:mysql://localhost/heistmvr
root
root
100
org.hibernate.dialect.MySQLDialect
org.hibernate.cache.internal.NoCacheProvider
true
true
update
以下是 pom.xml 文件中使用的依赖项:
XML
4.0.0
TablePerHierarchyAnnotation
TablePerHierarchyAnnotation
0.0.1-SNAPSHOT
jar
TablePerHierarchyAnnotation
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
org.hibernate
hibernate-core
5.2.6.Final
mysql
mysql-connector-java
6.0.5
org.hibernate
hibernate-annotations
3.5.6-Final
创建存储持久对象的类:
下面是Main 的实现。 Java文件:
Java
package com.exploit.db;
import com.exploit.model.C_Employee;
import com.exploit.model.Employee;
import com.exploit.model.P_Employee;
import com.exploit.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
public class Main {
public static void main(String[] args)
{
// Get session factory using Hibernate Util class
SessionFactory sessionFactory
= HibernateUtil.getSessionFactory();
// Get session from Sesson factory
Session session = sessionFactory.openSession();
// Begin transaction
Transaction transaction
= session.beginTransaction();
// Creating Employee base class record
Employee employee = new Employee();
employee.setName("KirikoChan");
employee.setAge(19);
// Creating Permanent Employee subclass record
P_Employee permanentEmployee = new P_Employee();
permanentEmployee.setName("Saili.H");
permanentEmployee.setAge(20);
permanentEmployee.setSalary(30000);
// Creating Contract Employee subclass record
C_Employee contractEmployee = new C_Employee();
contractEmployee.setName("ChikkoRita");
contractEmployee.setAge(21);
contractEmployee.setHourlyRate(2000);
contractEmployee.setDuration(7.5);
// persist all the employee records
session.persist(employee);
session.persist(permanentEmployee);
session.persist(contractEmployee);
// Commit the transaction and close the session
transaction.commit();
session.close();
System.out.println(
"Employee records successfully persisted.");
}
}
Main 类用于持久化所有三个类的对象实例。请注意,这两个类都保存在同一个表 Employee 中。鉴别器列用于区分实体。这是使用注释映射每个层次结构表的常用方法。