- Hibernate 教程
- Hibernate - 首页
- ORM - 概述
- Hibernate - 概述
- Hibernate - 架构
- Hibernate - 环境
- Hibernate - 配置
- Hibernate - 会话
- Hibernate - 持久化类
- Hibernate - 映射文件
- Hibernate - 映射类型
- Hibernate - 示例
- Hibernate - 对象关系映射
- Hibernate - 级联类型
- Hibernate - 注解
- Hibernate - 查询语言
- Hibernate - Criteria 查询
- Hibernate - 原生 SQL
- Hibernate - 缓存
- Hibernate - 实体生命周期
- Hibernate - 批量处理
- Hibernate - 拦截器
- Hibernate - ID 生成器
- Hibernate - 保存图片
- Hibernate - log4j 集成
- Hibernate - Spring 集成
- Hibernate - Struts 2 集成
- Hibernate - Web 应用程序
- 映射表示例
- Hibernate - 每层级一张表
- Hibernate - 每个具体类一张表
- Hibernate - 每个子类一张表
- Hibernate 有用资源
- Hibernate - 问答
- Hibernate - 快速指南
- Hibernate - 有用资源
- Hibernate - 讨论
Hibernate - 每个具体类一张表
引言
在 Hibernate 中,Java 类映射到数据库表。假设我们有一个类,并且它有几个子类,Hibernate 提供了三种方法将这些类映射到表:
每层级一张表
每个具体类一张表
每个子类一张表
让我们详细讨论一下“每个具体类一张表”以及一个示例。
每个具体类一张表
假设我们有一个类“Shape”,它有两个子类,“Circle”和“Rectangle”。在这种映射类型中,数据库中将有三个表。
层次结构中有三个类。**Shape** 是超类,**Circle** 和 **Rectangle** 是子类。子类的表将仅包含子类的字段。为了查看子类的所有字段,需要对超类和子类进行连接。
SELECT col1, col2…coln FROM superclass_table UNION SELECT col_a, col_b,..col_n FROM subclass_table;
这将选择子类(包括父类中的那些)的所有属性。**UNION** 运算符默认只选择不同的值。要允许重复值,请使用 **UNION ALL**。这就是为什么 **每个具体类一张表** 也被称为 **连接子类**。为了映射这些类,我们将在 *.hbm.xml 文件中使用 **union-subclass** 元素,如下所示:
<class name="com.tutorialspoint.Shape" table="shape">
...
<union-subclass name="com.tutorialspoint.Circle"
table="circle">
<property name="radius"></property>
</union-subclass>
<union-subclass name="com.tutorialspoint.Rectangle"
table="rectangle">
<property name="length"></property>
<property name="width"></property>
</union-subclass>
...
创建映射类
让我们创建其数据需要持久化到数据库中的 POJO 类。
Shape.java
package com.tutorialspoint;
public class Shape {
public int Id;
public String type;
public double area;
public Shape() {
this.type = "Shape";
}
public double calculateArea() {
this.area= 0;
setArea(area);
return area;
}
public int getId() {
return Id;
}
public void setId(int i) {
this.Id = i;
}
public String getType() {
return this.type;
}
public double getArea() {
return area;
}
public void setArea(double i) {
area = i;
}
}
Circle.java
package com.tutorialspoint;
import java.math.*;
public class Circle extends Shape {
private double radius;
public Circle(double rad ) {
this.radius = rad;
this.type = "Circle";
}
@Override
public double calculateArea() {
area = Math.PI * radius * radius;
return area;
}
public void setArea() {
this.area = calculateArea();
}
public double getArea() {
return area;
}
}
Rectangle.java
package com.tutorialspoint;
public class Rectangle extends Shape {
private double length, width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
this.type = "Rectangle";
}
@Override
public double calculateArea() {
return length * width;
}
public void setArea() {
this.area = calculateArea();
}
public double getArea() {
return area;
}
}
创建数据库表
让我们在数据库中创建表。将有三个表对应于上述对象,您希望提供持久性。考虑上述对象需要存储到以下 RDBMS 表中并从中检索:
CREATE TABLE students.shape( id int NOT NULL, type VARCHAR(20), area float ); CREATE TABLE students.circle( id int NOT NULL, type VARCHAR(20), area float, radius float ); CREATE TABLE students.rectangle( id int NOT NULL, type VARCHAR(20), area float, length float, width float );
创建映射配置文件
现在创建一个映射文件,该文件指示 Hibernate 如何将定义的类映射到数据库表。
shape.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 5.3//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.tutorialspoint.Shape" table="shape">
<id name="id">
<generator class="increment"></generator>
</id>
<property name="type"></property>
<property name="area"></property>
<union-subclass name="com.tutorialspoint.Circle"
table="circle">
<property name="radius"></property>
</union-subclass>
<union-subclass name="com.tutorialspoint.Rectangle"
table="rectangle">
<property name="length"></property>
<property name="width"></property>
</union-subclass>
</class>
</hibernate-mapping>
创建 Hibernate 配置文件
现在为数据库和其他详细信息创建一个 hibernate 配置文件。
hibernate.cfg.xml
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name = "hibernate.dialect">
org.hibernate.dialect.MySQL8Dialect
</property>
<property name = "hibernate.connection.driver_class">
com.mysql.cj.jdbc.Driver
</property>
<!—'students' is the database name -->
<property name = "hibernate.connection.url">
jdbc:mysql:///students
</property>
<property name = "hibernate.connection.username">
root
</property>
<property name = "hibernate.connection.password">
guest123
</property>
<!-- List of XML mapping files -->
<mapping resource = "shape.hbm.xml"/>
</session-factory>
</hibernate-configuration>
将属性 **hbm2ddlauto** 设置为 **update** 将在程序执行期间创建表(如果表不存在)。
创建应用程序类
最后,我们将使用 main() 方法创建我们的应用程序类来运行应用程序。我们将使用此应用程序来测试“每个具体类一张表”映射。
TestTablePerConcrete.java
package com.tutorialspoint;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
public class TestTablePerConcrete{ {
public static void main(String[] args) {
// create a hibernate configuration
StandardServiceRegistry ssr=new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
Metadata meta=new MetadataSources(ssr).getMetadataBuilder().build();
// get the sessionfactory and open the session
SessionFactory factory=meta.getSessionFactoryBuilder().build();
Session session=factory.openSession();
// begin the transaction
Transaction t=session.beginTransaction();
// create Shape instance and set details to persist
Shape s1=new Shape();
s1.setType(s1.getType());
s1.setArea(s1.calculateArea());
// create Circle instance and set details to persist
Circle c1=new Circle(2);
c1.setType(c1.getType());
c1.setArea();
// create Rectangle instance and set details to persist
Rectangle r1 = new Rectangle(3,4);
r1.setType(r1.getType());
r1.setArea();
// persist all instances
session.persist(s1);
session.persist(c1);
session.persist(r1);
// commit the transaction and close the session
t.commit();
session.close();
System.out.println(" Successfully persisted 3 classes. Please check your database for results.");
}
}
编译和执行
执行 TestTablePerHierarchy 二进制文件以运行程序。
输出
您将获得以下结果,并且记录将创建在 Shape 表中。
$java TestTablePerHierarchy Successfully persisted 3 classes. Please check your database for results.
如果您检查您的表,则它们应该包含以下记录:
mysql> select * from shape; +----+-------+------+ | id | type | area | +----+-------+------+ | 1 | Shape | 0 | +----+-------+------+ 1 row in set (0.00 sec) mysql> select * from circle; +----+--------+-------+--------+ | id | type | area | radius | +----+--------+-------+--------+ | 1 | Circle | 12.56 | 2 | +----+--------+-------+--------+ 1 row in set (0.00 sec) mysql> select * from rectangle; +----+-----------+------+--------+-------+ | id | type | area | length | width | +----+-----------+------+--------+-------+ | 1 | Rectangle | 12 | 3 | 4 | +----+-----------+------+--------+-------+ 1 row in set (0.00 sec)