1. 概述
在这个教程中,我们将回顾Hibernate的@Struct
注解,它允许开发人员创建自定义结构化类型。
结构化用户定义类型(也称为结构类型)的支持在SQL:1999标准中引入,这是对象关系映射(ORM)数据库的一个特性。结构或复合类型有其特定的应用场景,特别是自从SQL:2016标准引入JSON支持以来。
这些结构类型值提供了访问其子部分的能力,不像表中的行,它们没有标识符或主键。
2. 结构映射
Hibernate通过@Struct
注解类型让你能够为标注了@Embeddable
注解的类或@Embedded
属性指定结构化类型。
2.1. @Struct
用于映射结构化类型
考虑一个Department
类,它有一个@Embedded
的Manager
类(一个结构化类型):
@Entity
public class Department {
@Id
@GeneratedValue
private Integer id;
@Column
private String departmentName;
@Embedded
private Manager manager;
}
下面是带有@Struct
注解的Manager
类定义:
@Embeddable
@Struct(name = "Department_Manager_Type", attributes = {"firstName", "lastName", "qualification"})
public class Manager {
private String firstName;
private String lastName;
private String qualification;
}
2.2. @Embeddable
和@Struct
注解的区别
被@Struct
注解的类将映射到数据库中的自定义结构化用户类型。例如,如果没有@Struct
注解,@Embedded
的Manager
对象虽然是一个独立类型,但在Department
表中会作为一部分,如下面的DDL所示:
CREATE TABLE DEPRARTMENT (
Id BIGINT,
DepartmentName VARCHAR,
FirstName VARCHAR,
LastName VARCHAR,
Qualification VARCHAR
);
带有@Struct
注解的Manager
类将生成类似以下的用户自定义类型:
create type Department_Manager_Type as (
firstName VARCHAR,
lastName VARCHAR,
qualification VARCHAR
)
添加@Struct
注解后,Department
对象如下面的DDL所示:
CREATE TABLE DEPRARTMENT (
Id BIGINT,
DepartmentName VARCHAR,
Manager Department_Manager_Type
);
2.3. @Struct
注解与属性顺序
由于结构类型具有多个属性,正确地将数据映射到相应的属性非常重要。一种定义属性顺序的方法是通过@Struct
注解的attributes
字段。
在上面的Manager
类中,可以看到@Struct
注解的attributes
字段,它指定Hibernate在序列化和反序列化时期望Manager
属性的顺序为“firstName”,“lastName”最后是“qualification”。
另一种定义属性顺序的方法是通过Java记录,通过规范构造函数隐式指定顺序,例如:
@Embeddable
@Struct(name = "Department_Manager")
public record Manager(String lastName, String firstName, String qualification) {}
在这种情况下,Manager
记录的属性顺序将是“lastName”,“firstName”和“qualification”。
3. JSON映射
由于JSON是一种预定义的无结构类型,不需要定义类型名称或属性顺序。将@Embeddable
作为JSON映射可以通过在嵌入的字段/属性上使用@JdbcTypeCode(SqlTypes.JSON)
注解来完成。
例如,下面的类包含一个Manager
对象,它也是一个JSON无结构类型:
@Entity
public class Department_JsonHolder {
@Id
@GeneratedValue
private int id;
@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "department_manager_json")
private Manager manager;
}
上面类的预期DDL如下:
create table Department_JsonHolder as (
id int not null primary key,
department_manager_json json
)
以下是查询department_manager_json
列属性的HQL示例:
select djh.manager.firstName, djh.manager.lastName, djh.manager.qualifications
from department_jsonholder djh
4. 总结
@Embeddable
和@Embeddable @Struct
的主要区别在于后者在底层数据库中实际上是用户自定义类型。尽管许多数据库支持用户定义类型,但支持@Struct
注解的Hibernate方言包括:
- Oracle
- DB2
- PostgreSQL
在这篇文章中,我们讨论了Hibernate的@Struct
注解,如何使用它,以及何时将其添加到领域类中。
本文的源代码可在GitHub上获取。