【SpringData&JPA從入門到精通】01-JPA 註解
目錄
JPA 註解
基本註解
JPA 基本註解有 6 個:
@Entity
@Table
@Id
@GeneratedValue
@Column
@Basic
除此之外,還有 @Transient
、@Temporal
等註解
1、@Entity
@Entity
標註用於實體類宣告語句之前,指出該 Java 類為實體類,將對映到指定的資料庫表
如宣告一個實體類 Customer,它將對映到資料庫中的 customer 表上
@Entity
public class Customer
測試結果
Hibernate:
insert
into
Customer
(age, email, LAST_NAME)
values
(?, ?, ?)
可以發現,加了 @Entity
註解之後,Customer 變成了一個實體類,具備了與資料表的對映關係;只不過表名和類名是一樣的
2、@Table
當實體類與其對映的資料庫表不同名時,需要使用 @Table
標註說明。該標註與 @Entity
@Table
標註的常用選項是 name
,用於指明資料庫的表名
@Table
標註還有幾個選項:
-
catalog
和schema
,用於設定表所屬的資料庫目錄或模式,通常為資料庫名 -
uniqueConstraints
選項用於設定約束條件,通常不須設定
@Table(name = "JPA_CUSTOMERS")
@Entity
public class Customer
測試結果
Hibernate: insert into JPA_CUSTOMERS (age, email, LAST_NAME) values (?, ?, ?)
3、@Id
@Id
標註用於宣告一個實體類的屬性對映為資料庫的主鍵列。該屬性通常置於屬性宣告語句之前,可與宣告語句同行,也可寫在單獨行上
@Id
標註也可置於屬性的 Getter 方法之前
@Id
public Integer getId() {
return id;
}
4、@GeneratedValue
@GeneratedValue
用於標註主鍵的生成策略,通過 strategy
屬性指定
預設情況下,JPA 自動選擇一個最適合底層資料庫的主鍵生成策略:
- SQLServer 對應 identity
- MySQL 對應 auto increment
在 javax.persistence.GenerationType
中定義了以下幾種可供選擇的策略:
-
IDENTITY
:採用資料庫 ID 自增長的方式來自增主鍵欄位,Oracle 不支援這種方式 -
AUTO
:JPA 自動選擇合適的策略,是預設選項 -
SEQUENCE
:通過序列產生主鍵,通過@SequenceGenerator
註解指定序列名,MySQL 不支援這種方式 -
TABLE
:通過表產生主鍵,框架藉由表模擬序列產生主鍵,使用該策略可以使應用更易於資料庫移植
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
public Integer getId() {
return id;
}
5、@Basic
@Basic
表示一個簡單屬性到資料庫表字段的對映,對於沒有任何標註的 getXxx() 方法,預設即為 @Basic
-
fetch
:表示該屬性的讀取策略,有EAGER
和LAZY
兩種,分別表示主支抓取和延遲載入,預設為EAGER
-
optional
:表示該屬性是否允許為 null,預設為 true
@Basic
public String getEmail() {
return email;
}
6、@Column
當實體的屬性與其對映的資料庫表的列不同名時需要使用,@Column
標註通常置於實體的屬性宣告語句之前,還可與 @Id
標註一起使用
@Column
標註的常用屬性是 name
,用於設定對映資料庫表的列名。此外,該標註還包含其它多個屬性,如:unique
、nullable
、length
等
@Column
標註的 columnDefinition
屬性表示該欄位在資料庫中的實際型別
- 通常 ORM 框架可以根據屬性型別自動判斷資料庫中欄位的型別,但是對於 Date 型別仍無法確定資料庫中欄位型別究竟是
DATE
、TIME
還是TIMESTAMP
- 此外,String 的預設對映型別為
VARCHAR
,如果要將 String 型別對映到特定資料庫的BLOB
或TEXT
欄位型別
@Column
標註也可置於屬性的 Getter 方法之前
@Column(name = "LAST_NAME", length = 50, nullable = false)
public String getLastName() {
return lastName;
}
7、@Transient
表示該屬性並非是一個到資料庫表字段的對映,ORM 框架將忽略該屬性
如果一個屬性並非資料庫表的欄位對映,就務必將其標示為 @Transient
,否則 ORM 框架預設其註解為 @Basic
// 工具方法,不需要對映為資料表的一列
@Transient
public String getInfo() {
return "lastName: " + this.lastName + ", email: " + email;
}
8、@Temporal
在核心的 Java API 中並沒有定義 Date 型別的精度(temporal precision)
而在資料庫中,表示 Date 型別的資料有 DATE
、TIME
和 TIMESTAMP
三種精度(即單純的日期、時間或者兩者兼備)
在進行屬性對映時可使用 @Temporal
註解來調整精度
@Temporal(TemporalType.DATE)
public Date getBirthDay() {
return birthDay;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getCreateTime() {
return createTime;
}
測試結果
Hibernate:
insert
into
JPA_CUSTOMERS
(age, birthDay, createTime, email, LAST_NAME)
values
(?, ?, ?, ?, ?)
檢視資料表結構
查詢資料表資料
9、用 table 生成主鍵詳解
將當前主鍵的值單獨儲存到一個數據庫的表中,主鍵的值每次都是從指定的表中查詢來獲得
這種方法生成主鍵的策略可以適用於任何資料庫,不必擔心不同資料庫不相容造成的問題
1)準備工作
create table JPA_ID_GENERATOR
(
ID int(10) auto_increment,
PK_NAME varchar(50) not null,
PK_VALUE int(10) not null,
constraint JPA_ID_GENERATOR_pk
primary key (ID)
);
INSERT INTO jpa.jpa_id_generator (ID, PK_NAME, PK_VALUE) VALUES (1, 'CUSTOMER_ID', 1);
INSERT INTO jpa.jpa_id_generator (ID, PK_NAME, PK_VALUE) VALUES (2, 'STUDENT_ID', 10);
INSERT INTO jpa.jpa_id_generator (ID, PK_NAME, PK_VALUE) VALUES (3, 'ORDER_ID', 100);
表結構
表資料
2)編寫註解,@TableGenerator
和 @GeneratedValue
配合使用
@TableGenerator(
name = "ID_GENERATOR",
table = "JPA_ID_GENERATOR",
pkColumnName = "PK_NAME",
pkColumnValue = "CUSTOMER_ID",
valueColumnName = "PK_VALUE",
allocationSize = 100
)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ID_GENERATOR")
@Id
public Integer getId() {
return id;
}
其中 pkColumnName
、pkColumnValue
和 valueColumnName
之間的關係如下圖所示
@TableGenerator
註解中各個屬性詳解:
-
name
:主鍵生成策略名,與@GeneratedValue
註解中generator
值對應 -
table
:表生成策略所持久化的表名 -
pkColumnName
:在持久化表中,主鍵生成策略所對應的鍵 -
pkColumnValue
:在持久化表中,主鍵生成策略所對應的值 -
valueColumnName
:在持久化表中,主鍵當前所生成的值 -
allocationSize
:每次主鍵增加的大小
3)測試結果
後臺日誌資訊
Hibernate:
select
PK_VALUE
from
JPA_ID_GENERATOR
where
PK_NAME = 'CUSTOMER_ID' for update
Hibernate:
update
JPA_ID_GENERATOR
set
PK_VALUE = ?
where
PK_VALUE = ?
and PK_NAME = 'CUSTOMER_ID'
Hibernate:
insert
into
JPA_CUSTOMERS
(age, birthDay, createTime, email, LAST_NAME, id)
values
(?, ?, ?, ?, ?, ?)
JPA_ID_GENERATOR 表資料
JPA_CUSTOMERS 表資料
總結
本節重點掌握:
- 類註解
@Entity
、@Table
的作用 - 主鍵註解
Id
、@GeneratedValue
的作用 - 屬性註解
@Column
的作用 -
@Basic
和@Transient
註解的區別 -
@Temporal
註解的使用 -
@TableGenerator
註解的使用
附上導圖,僅供參考