MySQL主鍵自動產生和產生器表以及JPA主鍵映射

來源:互聯網
上載者:User

標籤:

MySQL主鍵自動產生表設計MySQL有許多主鍵建置原則,其中很常見的一種是自動產生。一般情況下,主鍵類型是BIGINT UNSIGNED,自動產生主鍵的關鍵詞是AUTO_INCREMENT。
CREATE TABLE Stock (id BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,    NO VARCHAR(255) NOT NULL,    name VARCHAR(255) NOT NULL,    price DECIMAL(6,2) NOT NULL,UNIQUE KEY Stock_NO (NO),    INDEX Stock_Name(name)) ENGINE = InnoDB;
JPA主鍵映射
@Entity@Table(name = "Stock", uniqueConstraints = {        @UniqueConstraint(name = "Stock_NO", columnNames = { "NO" })},indexes = {        @Index(name = "Stock_Name", columnList = "name")})public class Stock {private long id;    private String no;    private String name;    private double price;        @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)public long getId() {return id;}public void setId(long id) {this.id = id;}
 @GeneratedValue(strategy = GenerationType.IDENTITY):實體主鍵建置原則是自動產生,相容MySQL主鍵自動建置原則,關鍵詞是AUTO_INCREMENT。若是MySQL主鍵沒有指定AUTO_INCREMENT,報出以下異常。
javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not execute statementCaused by: org.hibernate.exception.GenericJDBCException: could not execute statementCaused by: java.sql.SQLException: Field 'id' doesn't have a default value
uniqueConstraints = {
        @UniqueConstraint(name = "Stock_NO", columnNames = { "NO" })
},
indexes = {
        @Index(name = "Stock_Name", columnList = "name")
}:建立唯一性索引,索引名字是Stock_NO,針對列是NO,建立索引,索引名字是Stock_Name,針對列是name。只有啟動了模式產生,索引產生的配置才會生效。啟用模式產生,在設定檔persistence.xml做如下配置:
<properties>            <property name="javax.persistence.schema-generation.database.action"                      value="drop-and-create" />        </properties>
模式產生雖然很方便,能自動產生表結構,但是,由它產生的表結構不總是最佳的,而且還不能保證是正確的。因此,作為最佳實務,不建議在生產環境啟用模式產生,手工維護表機構。禁用模式產生,在設定檔persistence.xml做如下配置:
 <properties>            <property name="javax.persistence.schema-generation.database.action"                      value="none" />        </properties>
產生器表主鍵的建置原則是產生器表,這種策略不常見,一般用於遺留資料庫使用JPA。否則的話,主鍵的建置原則一般會選擇自動產生(GenerationType.IDENTITY)或是序列產生(GenerationType.SEQUENCE)。往目標表插入一條資料之間,JPA實現者從產生器表選擇一條關於目標表的主鍵記錄,該記錄儲存目標表的主鍵。JPA實現者增大該主鍵值,然後把該主鍵增大之前的那個值插入目標表。MySQL產生器表
CREATE TABLE CreatorKey (  TableName VARCHAR(64) NOT NULL PRIMARY KEY,  KeyValue BIGINT UNSIGNED NOT NULL,  INDEX CreatorKey_Table_Values (TableName, KeyValue)) ENGINE = InnoDB;
MySQL目標表
CREATE TABLE Student (  id BIGINT UNSIGNED NOT NULL PRIMARY KEY,  name VARCHAR(100) NOT NULL,  INDEX Student_name (name)) ENGINE = InnoDB;
JPA主鍵映射
@Entity@Tablepublic class Student {private long id;private String name;@Id    @GeneratedValue(strategy = GenerationType.TABLE,            generator = "studentGenerator")    @TableGenerator(name = "studentGenerator", table = "creatorkey",            pkColumnName = "TableName", pkColumnValue = "Publishers",            valueColumnName = "KeyValue", initialValue = 1,            allocationSize = 1)    @Column(name = "studentId")public long getId() {return id;}
name :主鍵建置原則定義的名字;table:產生器表在資料庫中的名字;pkColumnName:產生器表的主鍵列的名字;pkColumnValue:產生器表主鍵列的值;valueColumnName:產生器表值列的名字;initialValue:產生器表初始值;allocationSize:產生器表數值遞增或遞減幅度。generator:主鍵建置原則定義的名字,該屬性與name屬性保持一致;generator = "studentGenerator":使用產生器表的主鍵建置原則。主鍵@TableGenerator的屬性initialValue,allocationSize根據原始碼,註解@TableGenerator的屬性initialValue、allocationSize是可選的,並且預設值分別是0、50。
  /**      * (Optional) The initial value to be used to initialize the column     * that stores the last value generated.     */    int initialValue() default 0;    /**     * (Optional) The amount to increment by when allocating id      * numbers from the generator.     */    int allocationSize() default 50;
但是,根據實際測試結果,情況並非如原始碼表示的那樣。清空產生器表creatorkey、目標表student,去掉屬性initialValue、allocationSize,執行持久化操作。
 Student student = new Student();            student.setName("張三");            manager.persist(student);
得到的結果卻是這樣的。                                                    從可以看出產生器表初始值並非為0,遞增或遞減幅度並非為50。而且每次重啟web server後,初始值和遞增幅度都是不確定的。更重要的是,主鍵的產生已經和產生器表失去了聯絡,KeyValue一致停留在某個值,不會變化。因此,建議在寫註解@TableGenerator時,雖然屬性 initialValue、 allocationSize是可選的,但要明確為這兩個屬性指定數值。令人驚訝的是,即使是明確為這兩個屬性指定數值,很多時候,也會出現上述的問題。經測試,把initialValue、 allocationSize都設定為1時,運行正常。主鍵@TableGenerator的範圍根據原始碼,在同一個持久化單元內,@TableGenerator的主鍵建置原則定義是全域的,可以被其他實體引用。
/** * Defines a primary key generator that may be  * referenced by name when a generator element is specified for  * the {@link GeneratedValue} annotation. A table 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).

但是,根據實際測試結果,情況並非如原始碼表示的那樣。即使在同一持久化單元內,@TableGenerator的主鍵建置原則定義只對定義它的實體生效。
@Entity@Tablepublic class Book implements Serializable{    private long id;    @Id    @GeneratedValue(strategy = GenerationType.TABLE,            generator = "studentGenerator")    public long getId()    {        return this.id;    }    public void setId(long id)    {        this.id = id;    }
啟動web server,報出如下異常。
javax.persistence.PersistenceException: [PersistenceUnit: EntityMappings] Unable to build Hibernate SessionFactoryCaused by: org.hibernate.AnnotationException: Unknown Id.generator: studentGeneratororg.hibernate.AnnotationException: Unknown Id.generator: studentGenerator
若在實體Book加上對主鍵建置原則的定義,就運行正常。
@Entity@Tablepublic class Book implements Serializable{    private long id;    @Id    @GeneratedValue(strategy = GenerationType.TABLE,            generator = "studentGenerator")    @TableGenerator(name = "studentGenerator", table = "creatorkey",            pkColumnName = "TableName", pkColumnValue = "Publishers",            valueColumnName = "KeyValue", initialValue = 1, allocationSize=1)    public long getId()    {        return this.id;    }    public void setId(long id)    {        this.id = id;    }





MySQL主鍵自動產生和產生器表以及JPA主鍵映射

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.