讓Primary Key交給JPA處理

讓Primary Key交給JPA處理

目的

透過本篇文章了解自動產生Primary Key的方法,大綱如下:

  • GeneratedValue
  • GenericGenerator (UUID)
  • SequenceGenerator (透過Database的sequence)

GeneratedValue快速產生Primary Key

GenerateValue最快速且最常用的方法,通常是直接使用GenerateValue annotation如下就結束

@Getter
@Setter
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue
    private long id;

    private String name;
}

更進一步了解,GenerateValue包含了strategy屬性,要讓他不做而外行為,自動生產的屬性有

  • GenerationType.IDENTITY
  • GenerationType.AUTO
    • 此為@GeneratedValue預設的策略參數,如沒特別設定則使用的參數就為此

注意: 不是每個資料庫都支援此功能

IDENTITY 和 AUTO 差異

GenerationType.AUTO是整個使用到此標籤的Primary key都共用一個記數器。

代表如果今天有兩個物件都自動產生Primary Key的話,當A物件產出後pk計數器則會跳到1,若是在產製B物件則此B物件的pk則會變成2,而不是從1開始。

GenerationType.IDENTITY則是使用到個別的計數器。

和上方AUTO成反例,A和B物件都會個別產出自己的計數器。

程式碼

@Data
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;
}

@Data
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
}


GeneratedValue搭配GenericGenerator產生UUID Primary Key

UUID是甚麼?

UUID全名為通用唯一辨識碼,言簡意賅地來說,就是這組辨識碼(Primary Key)幾乎永遠不會重複,在現在AI數據處理發達的現況,大數據處理資料爆棚的情況下,那就很適合直接將Primary Key設為UUID。

維基連結

設定

  • 告訴GeneratedValue要使用的產生器名稱
    • @GeneratedValue(generator = “system-uuid”)
  • 透過@GenericGenerator定義剛剛告訴GeneratedValue的generator
    • @GenericGenerator(name = “system-uuid”, strategy = “uuid”)

GenericGenerator

GenericGenerator的設定參數包含name和strategy,如同參數本身告訴開發者

  • name : 定義此Generator的名稱 (用於GeneratedValue)
  • strategy : 設定產生器的策略 (這邊使用uuid)

程式碼

@Data
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private long id;

    private String name;
}

GenerateValue搭配Database 裡的 Sequence

若是使用的Database不支援JPA自動產生的策略,而且目前開發沒有必要用到UUID的話那這就是最適合的方法了。

設定

如果上個章節UUID設定,要使用到Sequence也需要使用Generator,但JPA有提供專門使用的annotation,@SequenceGenerator

  • 告訴GeneratedValue要使用的產生器名稱,並且告訴他要使用的策略
    • @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = “userGenerator”)
  • @SequenceGenerator透過定義userGenerator這個產生器
    • @SequenceGenerator(name = “userGenerator”, sequenceName = “user_sequence_generator”, initialValue = 1, allocationSize = 1)

@SequenceGenerator

上方的設定可以看到SequenceGenerator要設定的參數較多,參數個別的意義如下

  • name : 定義此Generator的名稱 (用於GeneratedValue)
  • sequenceName : 和資料庫建立的sequence對應
  • initialValue : 計數器的初始直
  • allocationSize : 計數器每次跳得值

程式碼

@Data
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userGenerator")
    @SequenceGenerator(name = "userGenerator", sequenceName = "user_sequence_generator", initialValue = 1, allocationSize = 1)
    private long id;

    private String name;
}


總結

今天討論了

  • 快速又簡單的AUTO和IDENTITY,但不是每個資料庫都支援

    • MySql、H2支援但Oracle系列則否
  • 透過GenericGenerator產出幾乎不會重複的UUID當作Primary Key

  • 讓Database 的squence來掌管計數器的SequenceGenerator

    • 在使用之前請務必確定你的資料庫已經建立squence
      • 建立的方法只要你資料庫的名稱+squence即可搜尋到
      • Oracle squence

程式碼中使用到的Getter/Setter/Data為lombok自動產生的插件,如果沒有使用的讀者可以自己撰寫get和set方法。

留言

這個網誌中的熱門文章

Java Lambda Map篇

(InterviewBit) System Design - Design Cache System

設計模式 - 享元模式 (Structural Patterns - Flyweight Design Pattern)