Hibernate 6 中的序列命名策略
一、簡介
在本教程中,我們將探討如何設定 Hibernate 6 的資料庫序列隱式命名策略。 Hibernate 6 引入了幾種新的命名策略,這些策略會影響序列的命名和使用方式。
2. 標準命名策略
預設情況下,Hibernate 6 使用標準命名策略。它使用標準命名約定根據實體名稱和列名稱產生序列名稱。例如,如果我們有一個實體Person ,其列為id ,則序列名稱將為person_seq 。
為了使用標準的命名策略,我們需要在application.properties中針對不同的命名策略新增必要的設定。以下是如何設定每個命名策略的配置:
spring.jpa.properties.hibernate.id.db_structure_naming_strategy=standard
讓我們來看一個基本的Person實體類別來說明命名約定:
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String name;
// setters and getters
}
在此範例中,由於我們使用標準策略,Hibernate 在建立表格的同時自動產生名為person_seq的序列:
Hibernate:
create table person (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence person_seq start with 1 increment by 50
標準策略的一個關鍵點是其預設增量值。 Hibernate 分配一個更大的值(例如50來最佳化批次操作,減少序列檢索所需的資料庫呼叫次數。
當我們插入Person記錄時,Hibernate使用person_seq序列來產生主鍵:
Hibernate:
select next value for person_seq
Hibernate:
insert
into person (name,id)
values (?,?)
此外,我們可以使用@Table註釋來覆蓋表格映射。這允許我們指定一個自訂表名稱,然後用於產生對應的序列名稱。
例如,如果我們有一個具有列id的實體Person ,我們可以指定自訂表格名稱my_person_table來產生序列名稱my_person_table _seq :
@Entity
@Table(name = "my_person_table")
public class Person {
// ...
}
在本例中,表格名稱為my_person_table ,產生的序列名稱為my_person_table_seq :
Hibernate:
create table my_person_table (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence my_person_table_seq start with 1 increment by 50
當我們嘗試插入Person記錄時,Hibernate 使用my_person_table_seq產生主鍵值:
Hibernate:
select
next value for my_person_table_seq
3. 遺留命名策略
此策略與標準策略類似,但它使用舊的命名約定或產生器名稱(如果指定產生序列名稱)。例如,如果我們有一個具有列id的實體Person ,則序列名稱將為hibernate_sequence 。此外, hibernate_sequence序列用於所有實體。
為了啟用遺留策略,我們在application.properties檔案中將屬性hibernate.id.db_structure_naming_strategy設定為legacy :
spring.jpa.properties.hibernate.id.db_structure_naming_strategy=legacy
讓我們考慮一下使用遺留策略的現有Person實體類別。在這種情況下,Hibernate 會建立表格和一個名為hibernate_sequence且具有相同表名的序列:
Hibernate:
create table person (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence hibernate_sequence start with 1 increment by 1
與標準命名策略相反,當使用舊命名策略時,序列的預設增量值通常為1 。這意味著序列產生的每個新值都會加1.
當插入Person記錄時,Hibernate依賴hibernate_sequence來產生主鍵:
Hibernate:
select next value for hibernate_sequence
Hibernate:
insert
into person (name,id)
values (?,?)
即使使用遺留策略,我們也可以使用@Table註解自訂表名稱。在這種情況下,產生的序列名稱將不會反映表名稱。
但是,我們可以使用@SequenceGenerator註解指定自訂序列名稱。這對於管理特定實體的序列特別有用:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_custom_seq")
@SequenceGenerator(name = "person_custom_seq", sequenceName = "person_custom_seq", allocationSize = 10)
private Long id;
在此範例中,我們使用@SequenceGenerator註解指定分配大小為10自訂序列名稱person_custom_seq 。 @GeneratedValue註解設定為使用此序列產生器:
Hibernate:
create table my_person_table (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence person_custom_seq start with 1 increment by 10
當插入Person記錄時,Hibernate 透過執行下列 SQL 語句從person_custom_seq序列中檢索下一個可用值:
Hibernate:
select next value for person_custom_seq
遺留策略主要旨在保持與舊版本 Hibernate 的兼容性並避免破壞現有系統。
4.單一命名策略
Hibernate 6 引入了單一命名策略,透過對同一模式中的所有實體使用統一的序列名稱來簡化序列命名。與傳統策略類似,當使用單一命名策略時,Hibernate 會產生一個名為hibernate_sequence的單一序列,該序列在模式中的所有實體之間共用。
這對於確保序列管理的一致性方法特別有用。讓我們看看這如何處理兩個不同的實體: Person和Book 。
要使用單一命名策略,我們需要在application.properties檔案中進行設定:
spring.jpa.properties.hibernate.id.db_structure_naming_strategy=single
在這裡,我們將使用單一命名策略建立兩個實體: Person和Book :
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
private String title;
// setters and getters
}
當使用單一命名策略時,Hibernate 會為所有實體產生單一序列。實體的 SQL 語句可能如下所示:
Hibernate:
create table book (
id bigint not null,
title varchar(255),
primary key (id)
)
Hibernate:
create table person (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence hibernate_sequence start with 1 increment by 1
這裡我們看到只建立了一個序列hibernate_sequence 。因此,當向Person和Book表插入記錄時,Hibernate 使用hibernate_sequence序列來產生主鍵值:
Person person = new Person();
person.setName("John Doe");
personRepository.save(person);
Book book = new Book();
book.setTitle("Baeldung");
bookRepository.save(book);
List<Person> personList = personRepository.findAll();
List<Book> bookList = bookRepository.findAll();
assertEquals((long)1,(long) personList.get(0).getId());
assertEquals((long)2, (long) bookList.get(0).getId());
在此範例中,我們建立並儲存兩個實體: Person和Book 。兩個實體應使用相同的序列產生器來產生主鍵。當我們先儲存Person ,然後儲存Book時, Person應該會獲得 ID 1 , Book應該會獲得 ID 2 。
5. 自訂命名策略
此外,我們也可以透過自訂命名策略來定義自己的序列命名約定。要對序列使用自訂命名策略,我們首先需要建立ImplicitDatabaseObjectNamingStrategy的自訂實作。此介面用於為各種資料庫物件(包括序列)提供自訂命名策略。
以下是我們如何建立ImplicitDatabaseObjectNamingStrategy的自訂實作來自訂序列名稱:
public class CustomSequenceNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
@Override
public QualifiedName determineSequenceName(Identifier catalogName, Identifier schemaName, Map<?, ?> map, ServiceRegistry serviceRegistry) {
JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
String seqName = ((String) map.get("jpa_entity_name")).concat("_custom_seq");
return new QualifiedSequenceName(
catalogName,
schemaName,
jdbcEnvironment.getIdentifierHelper().toIdentifier(seqName));
}
// others methods
}
在determineSequenceName()方法中,我們自訂序列名稱的產生。首先,我們使用JdbcEnvironment服務來存取各種與資料庫相關的實用程序,這有助於我們有效地管理資料庫物件名稱。然後,我們透過將_custom_seq後綴附加到實體名稱來建立自訂序列名稱。這種方法允許我們控制資料庫模式中的序列名稱格式。
接下來,我們需要設定 Hibernate 以使用我們的自訂命名策略:
spring.jpa.properties.hibernate.id.db_structure_naming_strategy=com.baeldung.sequencenaming.CustomSequenceNamingStrategy
透過自訂ImplicitDatabaseObjectNamingStrategy ,Hibernate 會使用我們定義的自訂序列名稱來產生 SQL 語句:
Hibernate:
create table person (
id bigint not null,
name varchar(255),
primary key (id)
)
Hibernate:
create sequence person_custom_seq start with 1 increment by 50
除了ImplicitDatabaseObjectNamingStrategy之外,我們還可以使用PhysicalNamingStrategy ,它定義了所有資料庫物件的全面命名約定。透過PhysicalNamingStrategy ,我們能夠實現複雜的命名規則,這些規則不僅適用於序列,也適用於其他資料庫物件。
以下是如何使用PhysicalNamingStrategy實作自訂序列命名的範例:
public class CustomPhysicalNamingStrategy extends DelegatingPhysicalNamingStrategy {
@Override
public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) {
return new Identifier(name.getText() + "_custom_seq", name.isQuoted());
}
// other methods for tables and columns
}
六、結論
在本文中,我們探討如何在 Hibernate 6 中使用自訂命名策略。此外,自訂命名策略允許我們自訂序列命名約定。
與往常一樣,範例的原始程式碼可在 GitHub 上取得。