Spring JPA - 自定義Entity的identifier生成方式

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生成器。

參考文獻

  1. How to combine the Hibernate assigned generator with a sequence or an identity column
  2. Why you should never use the TABLE identifier generator with JPA and Hibernate
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章