@GeneratedValue源碼解析

JPA要求每個實體必須有且只有一個主鍵,而@GeneratedValue提供了主鍵的生成策略,這就是@GeneratedValue註解存在的意義。本文將淺析@GeneratedValue的源碼。php

@GeneratedValue的源碼以下:html

/*
 * Copyright (c) 2008, 2009, 2011 Oracle, Inc. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
 * which accompanies this distribution.  The Eclipse Public License is available
 * at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License
 * is available at http://www.eclipse.org/org/documents/edl-v10.php.
 */
package javax.persistence;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static javax.persistence.GenerationType.AUTO;

/**
 * Provides for the specification of generation strategies for the
 * values of primary keys.
 *
 * <p> The <code>GeneratedValue</code> annotation
 * may be applied to a primary key property or field of an entity or
 * mapped superclass in conjunction with the {@link Id} annotation.
 * The use of the <code>GeneratedValue</code> annotation is only
 * required to be supported for simple primary keys.  Use of the
 * <code>GeneratedValue</code> annotation is not supported for derived
 * primary keys.
 *
 * <pre>
 *
 *     Example 1:
 *
 *     &#064;Id
 *     &#064;GeneratedValue(strategy=SEQUENCE, generator="CUST_SEQ")
 *     &#064;Column(name="CUST_ID")
 *     public Long getId() { return id; }
 *
 *     Example 2:
 *
 *     &#064;Id
 *     &#064;GeneratedValue(strategy=TABLE, generator="CUST_GEN")
 *     &#064;Column(name="CUST_ID")
 *     Long id;
 * </pre>
 *
 * @see Id
 * @see TableGenerator
 * @see SequenceGenerator
 *
 * @since Java Persistence 1.0
 */
@Target({METHOD, FIELD})
@Retention(RUNTIME)

public @interface GeneratedValue {

    /**
     * (Optional) The primary key generation strategy
     * that the persistence provider must use to
     * generate the annotated entity primary key.
     */
    GenerationType strategy() default AUTO;

    /**
     * (Optional) The name of the primary key generator
     * to use as specified in the {@link SequenceGenerator}
     * or {@link TableGenerator} annotation.
     * <p> Defaults to the id generator supplied by persistence provider.
     */
    String generator() default "";
}

@Target({METHOD, FIELD})說明該註解能夠用於方法聲明和域聲明。java

@Retention(RUNTIME)說明該註解在VM運行期間也能夠保留,能夠經過反射機制讀取註解的信息。數據庫

若是不是很清楚,可參考@Controller和@Restcontroller源碼解析中有對元註解的介紹。app

@GeneratedValue註解有兩個屬性,分別是strategy和generator,其中generator屬性的值是一個字符串,默認爲"",其聲明瞭主鍵生成器的名稱。eclipse

查看GenerationType的源碼,能夠看到定義了四種主鍵生成策略:TABLE,SEQUENCE,IDENTITY,AUTO。ide

/*
 * Copyright (c) 2008, 2009, 2011 Oracle, Inc. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
 * which accompanies this distribution.  The Eclipse Public License is available
 * at http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License
 * is available at http://www.eclipse.org/org/documents/edl-v10.php.
 */
package javax.persistence;

/**
 * Defines the types of primary key generation strategies.
 *
 * @see GeneratedValue
 *
 * @since Java Persistence 1.0
 */
public enum GenerationType {

    /**
     * Indicates that the persistence provider must assign
     * primary keys for the entity using an underlying
     * database table to ensure uniqueness.
     */
    TABLE,

    /**
     * Indicates that the persistence provider must assign
     * primary keys for the entity using a database sequence.
     */
    SEQUENCE,

    /**
     * Indicates that the persistence provider must assign
     * primary keys for the entity using a database identity column.
     */
    IDENTITY,

    /**
     * Indicates that the persistence provider should pick an
     * appropriate strategy for the particular database. The
     * <code>AUTO</code> generation strategy may expect a database
     * resource to exist, or it may attempt to create one. A vendor
     * may provide documentation on how to create such resources
     * in the event that it does not support schema generation
     * or cannot create the schema resource at runtime.
     */
    AUTO
}

TABLEui

使用數據庫表來生成主鍵。該策略通常與另一個註解一塊兒使用@TableGenerator,@TableGenerator註解指定了生成主鍵的表(能夠在實體類上指定也能夠在主鍵字段或屬性上指定),而後JPA將會根據註解內容自動生成一張表做爲序列表(或使用現有的序列表)。若是不指定序列表,則會生成一張默認的序列表,表中的列名也是自動生成,數據庫上會生成一張名爲sequence的表(SEQ_NAME,SEQ_COUNT)。序列表通常只包含兩個字段:第一個字段是該生成策略的名稱,第二個字段是該關係表的最大序號,它會隨着數據的插入逐漸累加。該策略的好處就是不依賴於外部環境和數據庫的具體實現,便於移植;但因爲其不能充分利用數據庫的特性,因此不會優先使用。this

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "roleSeq")
    @TableGenerator(name = "roleSeq", allocationSize = 1, table = "seq_table", pkColumnName = "seq_id", valueColumnName = "seq_count")
    private Long id;

SEQUENCEspa

使用序列來生成主鍵。 該策略的不足之處正好與TABLE相反,因爲只有部分數據庫(Oracle,PostgreSQL,DB2)支持序列對象,因此該策略通常不該用於其餘數據庫。須要注意,MySQL不支持這種主鍵生成策略。該策略通常與另一個註解一塊兒使用@SequenceGenerator,@SequenceGenerator註解指定了生成主鍵的序列.而後JPA會根據註解內容建立一個序列(或使用一個現有的序列)。若是不指定序列,則會自動生成一個序列SEQ_GEN_SEQUENCE。

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "menuSeq")
    @SequenceGenerator(name = "menuSeq", initialValue = 1, allocationSize = 1, sequenceName = "MENU_SEQUENCE")
    private Long id;

IDENTITY

使用數據庫ID自增加的方式來生成主鍵。 該策略在大部分數據庫中都提供了支持(指定方法或關鍵字可能不一樣),但仍是有少數數據庫(Oracle)不支持,因此可移植性略差。

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

AUTO

自動選擇合適的主鍵生成策略。該策略比較經常使用,也是默認選項,@GeneratedValue(strategy = GenerationType.AUTO)至關於@GeneratedValue。

    @Id
    @GeneratedValue
    private Long id;

參考:JPA之@GeneratedValue註解。這篇介紹的挺詳細的,推薦一下。

相關文章
相關標籤/搜索