Hibernate中@Struct註解型別

banq發表於2024-03-31

在本教程中,我們將回顧 Hibernate 的@Struct註釋,它允許開發人員建立結構化的使用者定義型別。

  • Hibernate 允許您透過@Struct註釋型別為使用@Embeddable註釋或@Embedded屬性註釋的類 指定結構化型別。
  • SQL:1999 標準中引入了對結構化使用者定義型別(又稱為結構化型別)的支援,這是物件關係 (ORM) 資料庫的一項功能。

結構化或複合型別有其用例,特別是在 SQL:2016 標準中引入了對 JSON 的支援之後。這些結構化型別的值提供對其子部分的訪問,並且沒有像表中的行那樣的識別符號或主鍵。

@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 = <font>"Department_Manager_Type", attributes = {"firstName", "lastName", "qualification"})
public class Manager {
    private String firstName;
    
    private String lastName;
    
    private String qualification;
}

@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
);

@Struct註解和屬性順序
由於結構化型別具有多個屬性,因此屬性的順序對於將資料對映到正確的屬性非常重要。定義屬性順序的一種方法是透過 @Struct 註解的 "attributes "欄位。

在上面的 Manager 類中,你可以看到 @Struct 註解中的 "attributes "欄位,它規定 Hibernate 期望 Manager 屬性(在序列化和去序列化時)的順序是 "firstName"(名字)、"lastName"(姓氏)和 "qualification"(資格)。

定義屬性順序的第二種方法是使用 Java 記錄,透過規範建構函式隱式指定順序,例如

@Embeddable
@Struct(name = <font>"Department_Manager")
public record Manager(String lastName, String firstName, String qualification) {}

上面,Manager 記錄屬性將具有以下順序:“lastName”、“firstName”和“qualification”。

JSON 對映
由於 JSON 是預定義的非結構化型別,因此無需定義型別名稱或屬性順序。透過用 @JdbcTypeCode(SqlTypes.JSON)註釋嵌入欄位/屬性,可將 @Embeddable 對映為 JSON。

例如,下面的類持有一個 Manager 物件,該物件也是 JSON 非結構化型別:

@Entity
public class Department_JsonHolder {
    @Id
    @GeneratedValue
    private int id;
    
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = <font>"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

結論
@Embeddable和@Embeddable @Struct之間的區別在於:後者實際上是底層資料庫中的使用者定義型別(user-defined type )。雖然許多資料庫支援使用者定義型別,但支援@Struct註解的 hibernate 方言有:

  • Oracle
  • DB2
  • PostgreSQL

 

相關文章