identifier簡介
identifiers在JPA中代表着數據實體的主鍵,JPA支持兩種主要類型的標識符:
- 人爲分配的(assigned)
- 自動產生的(generated)
對於assigned類型的identifier,在持久化之前,必須在每個給定實體上設置標識符。因此,assigned類型的標識符適用於自然鍵(實體的屬性可以作爲主鍵唯一標識該實體)。
對於合成主鍵(人爲定義的字段作爲唯一標識實體的標誌),我們需要使用generated類型的實體標識符,JPA通過使用@GeneratedValue註解來自動生成標識符。
GenerationType枚舉定義了四種類型的生成的標識符策略:
- AUTO
- IDENTITY
- SEQUENCE
- TABLE
AUTO標識符生成器策略根據基礎關係數據庫功能選擇其他三個策略之一(IDENTITY,SEQUENCE或TABLE)。
IDENTITY生成器依賴數據庫表中一個自動遞增的列(例如SQL Server中的IDENTITY或MySQL中的AUTO_INCREMENT),SEQUENCE生長期依賴一個與表無關的數據庫序列,TABLE生成器在關係數據庫中沒有直接實現,它是依賴在數據庫中一張存儲identifier的表。
Assigned類型的identifier實現如下:
@Id
private Long id;
Generated類型的identifier實現如下:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
自定義identifier生成方式
在使用JPA的過程有自定義identifier的需求,例如:在一個用戶管理系統中,需要預留一部分id號碼(如10000以內的號碼)給特殊的用戶,而普通用戶則使用自動生成的id,這時使用默認的方式是不能滿足需求的,好在Spring JPA中提供了便捷的自定義identifier的方式。
首先,需要讓實體實現以下接口:
public interface Identifiable<T extends Serializable> {
T getId();
}
爲了能自定義identifier,我們可以寫一個如下的identifier生成策略:
public class AssignedIdentityGenerator extends IdentityGenerator {
@Override
public Serializable generate(SessionImplementor session, Object obj) {
if(obj instanceof Identifiable) {
Identifiable identifiable = (Identifiable) obj;
Serializable id = identifiable.getId();
if(id != null) {
return id;
}
}
return super.generate(session, obj);
}
}
如果實體沒有設定id,則使用默認的自增策略,如果有設定的id,則使用設定的id,採用該策略的實體的寫法爲:
@Entity(
public class Post implements Identifiable<Long> {
@Id
@GenericGenerator(
name = "assigned-identity",
strategy = "com.vladmihalcea.book.hpjp.hibernate.identifier.AssignedIdentityGenerator"
)
@GeneratedValue(
generator = "assigned-identity",
strategy = GenerationType.IDENTITY
)
private Long id;
public Post() {
}
public Post(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
}
在@GenericGenerator註解中標識出該生成器的名字和依賴的類,在@GeneratedValue註解中指明使用生成器的名字,即可實現使用自定義的id生成器。