Oracle序列和主鍵映射

來源:互聯網
上載者:User

標籤:

前言

每張表都有主鍵,可分別簡單主鍵和組合主鍵,簡單主鍵為表中的一列,組合主鍵為表中的幾列。主鍵的建置原則有許多種,其中,序列是oracle常見的主鍵建置原則之一。本文主要講解JPA映射主鍵的技術細節。其中,主鍵建置原則是oracle序列,JPA實現是Hibernate。

oracle序列建立序列
drop sequence testsequence;Create sequence testsequence Increment by 1 Start with 1 NOMAXVALUE NOMINVALUE Nocycle nocache;

序列testsequence,從1開始遞增,每次遞增1。不指定最大值、最小值、不迴圈、不緩衝。

建立表
create table TEST(  id   NUMBER not null,  name VARCHAR2(30));alter table TEST  add constraint PK_ID primary key (ID);create table TEST2(  id   NUMBER not null,  name VARCHAR2(30));alter table TEST2  add constraint PK_TEST2_ID primary key (ID);

建立了兩張表,TEST、TEST2。表結構完全一致,簡單主鍵ID,名字name。

建立觸發器
CREATE OR REPLACE TRIGGER "TG_TEST" BEFORE INSERT ON TEST FOR EACH ROW  WHEN (new.id is null) beginselect testsequence.nextval into:new.id from dual;end;/ALTER TRIGGER "TG_TEST" ENABLE;CREATE OR REPLACE TRIGGER "TG_TEST2" BEFORE INSERT ON TEST2 FOR EACH ROW  WHEN (new.id is null) beginselect testsequence.nextval into:new.id from dual;end;/ALTER TRIGGER "TG_TEST" ENABLE;

定義兩張表TEST、TEST2的主鍵建置原則是序列testsequence。

JPA主鍵映射註解使用JPA映射主鍵,若主鍵的建置原則是序列的話,需要使用到四個註解,分別是@Id、@Column、@SequenceGenerator、@GeneratedValue。註解@Id表示該實體屬性對應資料庫的主鍵欄位,註解@Column表示該實體屬性對應資料的欄位的名稱,@SequenceGenerator定義一個序列, @GeneratedValue應用一個序列。
private long id;    @Id    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")    @SequenceGenerator(name="sequence", sequenceName="testSequence", initialValue=1, allocationSize=1)    @Column(name = "ID")    public long getId()    {        return this.id;    }    public void setId(long id)    {        this.id = id;    }
@SequenceGenerator,屬性name,表示序列定義的名稱,屬性sequenceName,表示序列的名稱。這兩個屬性的解釋很像,但並非一回事。屬性name指的是序列定義本身的名稱,屬性sequenceName表示該定義涉及到的序列的名稱。屬性initialValue,表示序列初始值,屬性allocationSize,表示序列遞增或遞減的幅度。@GeneratedValue,屬性strategy,表示主鍵建置原則,GenerationType.SEQUENCE表示主鍵建置原則是序列,屬性generator,表示應用序列定義的名稱。@GeneratedValue的屬性generator和@SequenceGenerator的屬性name保持一致。現在,執行持久化動作。
 Test test = new Test(); test.setName("John Wiley & Sons"); manager.persist(test);
查詢資料庫,資料的情況如下:

根據原始碼,註解@SequenceGenerator的屬性initialValue、 allocationSize為可選項,預設值分別是1、50。
 /**      * (Optional) The value from which the sequence object      * is to start generating.     */    int initialValue() default 1;    /**     * (Optional) The amount to increment by when allocating      * sequence numbers from the sequence.     */    int allocationSize() default 50;
但是,根據測試,結果並非如原始碼展示的那樣。以上序列重建立立、清空表TEST的資料,把@SequenceGenerator的屬性initialValue、 allocationSize去掉,保持預設。執行持久化實體的動作。查詢資料庫,資料的情況如下:
若是再一次重建立立以上序列,清空表TEST的資料,重啟web server,執行實體持久化實體的工作,資料庫的ID並不一定從100開始。也就是說initiaValue的值是隨機的,allocationSize也並非是50。而且,從插入表中的主鍵數值看來,已經脫離了序列的運作。從可以看出,序列testSequence的LAST_NUMBER 是3,但是程式插入的主鍵數值卻是100,101。因此,建議在寫註解@SequenceGenerator時,雖然屬性 initialValue、 allocationSize是可選的,但要明確為這兩個屬性指定數值,並保持和資料庫對序列的定義完全一致。應用範圍根據原始碼,在持久化單元內,序列定義是全域。在一個實體內定義的序列定義,可以應用於持久化單元內的其他實體。
/** * Defines a primary key generator that may be referenced by name when * a generator element is specified for the {@link GeneratedValue} * annotation. A sequence generator may be specified on the entity * class or on the primary key field or property. The scope of the * generator name is global to the persistence unit (across all * generator types). * * <pre> *   Example: * *   @SequenceGenerator(name="EMP_SEQ", allocationSize=25) * </pre> * * @since Java Persistence 1.0 */
但是,根據測試,在持久化單元內,序列定義只針對定義它的實體有效。在實體TEST內定義了一個序列定義,名稱為sequence。現在在實體TEST2應用這個序列定義。
  private long id;    @Id    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")    @Column(name = "ID")    public long getId()    {        return this.id;    }    public void setId(long id)    {        this.id = id;    }
啟動web server,報出錯誤Unknown Id.generator: sequence。
private long id;    @Id    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence")    @SequenceGenerator(name="sequence", sequenceName="testSequence", initialValue=1, allocationSize=1)    @Column(name = "ID")    public long getId()    {        return this.id;    }    public void setId(long id)    {        this.id = id;    }
以上代碼,在實體TEST2內,針對序列testSequence,重新定義了序列定義,持久化一切正常。因此,序列定義只針對定義它的實體有效。在生產環境中,不同的表應該使用不同的序列。這樣才能最大限度保證序列產生的數值在特定的表中,其主鍵數值具有連續性。比如說,一個序列產生的數值類似1、2、3、4、5......在該序列同時應用在表TEST,TEST2,有可能數值1、2分配給了TEST,而把3、4、5分配給了TEST2,這樣看起來,表中的主鍵數值就常常沒有連續性。當然,序列只分配給某個表,也不能保證該表的主鍵數值就一定會有連續性。當遇到交易回復時,序列產生的數值同樣沒有插入到表的主鍵,造成主鍵數值的不連續。




Oracle序列和主鍵映射

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.