1. 程式人生 > >JPA註解的使用,用於實體類的註解

JPA註解的使用,用於實體類的註解

1、 @Entity(name=”EntityName”)

      表示該類是一個可持化的實體。當在容器中時,伺服器將會首先載入所有標註了@Entity註釋的實體類,其中@Entity中的“name”屬性表示實體名稱,若不作設定,預設為標註實體類的名稱(注意大小寫與系統的關係。)。 @Entity標註是必需的 ,name屬性為可選。 

Java程式碼  收藏程式碼
  1. @Entity(name=“person_1”)  
  2. public class Person implements Serializable {  
  3.     public Person(){  
  4.         id=System.currentTimeMillis();  
  5.     }  
  6.     public Person(Long id){  
  7.         this.id = id;  
  8.     }  
  9. }  

 @Entity標註的實體類至少需要有一個無參的構造方法。這是因為,在使用類反射機制 Class.newInstance()方法建立例項時,必需要有一個預設的無引數構造方法,否則會執出例項化異常(InstantiationException)。

   如果指定name屬性後,在執行JPQL時應該使用name屬性所指的名稱。像上面的標註後,在執行JPQL時要像下面這樣:

Sql程式碼  收藏程式碼
  1. SELECT p FROM person_1 AS
     p  

 name屬性為預設值時就使用類名稱:

Sql程式碼  收藏程式碼
  1. SELECT p FROM Person AS p;   

    有兩點須要注意:

      (1)實體可繼承,非實體類可以繼承自實體類,實體類也要中以繼承自非實類。

      (2)抽象類(abstract)也可以標註為實體類。

2、@Table

     在使用@Table標記時,需要注意以下幾個問題。

     (1) 此標記需要標註在類名前,不能標註在方法或屬性前。

     (2) name 屬性表示實體所對應表的名稱,預設表名為實體名稱。

     (3) catalog

 和schema 屬性表示實體指定的目錄名或資料庫名,這個根據不同的資料型別有所不同。

     (4) uniqueConstraints 屬性表示該實體所關聯的唯一約束條件,一個實體可以有多個唯一的約束,預設沒有約束條件。

     (5)若使用uniqueContraints 屬性時,需要配合標記UniqueContraint標記來使用。

Java程式碼  收藏程式碼
  1. package model;  
  2. import java.io.Serializable;  
  3. import javax.persistence.Entity;  
  4. import javax.persistence.Table;  
  5. import javax.persistence.UniqueConstraint;  
  6. @Entity  
  7. @Table(name = “tb_contact”, schema = “test”, uniqueConstraints = {   
  8.         @UniqueConstraint(columnNames = {“name”“email” }),  
  9.         @UniqueConstraint(columnNames = {“col1”“col2” })  
  10. })  
  11. public class ContactEO implements Serializable {  
  12.     private Long id;  
  13.     private String name;  
  14.     private String email;  
  15.     private String col1;  
  16.     private String col2;  
  17. }  

 以上的@Table註釋表示指定資料庫名“test”,表名為“tb_contact”,並建立了兩組唯一索引。

3、@Column

        @Column標記表示持久化屬性對映表中的欄位。此標記可以標註在Getter方法或屬性前。

如標註在屬性前

Java程式碼  收藏程式碼
  1. public class ContactEO implements Serializable {  
  2.     @Column(name = “name”)  
  3.     private String name;  
  4.     public String getName() {  
  5.         return name;  
  6.     }  
  7.     public void setName(String name) {  
  8.         this.name = name;  
  9.     }  
  10. }  

 或者標註在Getter方法前。

Java程式碼  收藏程式碼
  1. public class ContactEO implements Serializable {  
  2.     private String name;  
  3.     @Column(name = “name”)  
  4.     public String getName() {  
  5.         return name;  
  6.     }  
  7.     public void setName(String name) {  
  8.         this.name = name;  
  9.     }  
  10. }  

  (1) unique 屬性表示該欄位是否為唯一標識,預設為false。如果表中有一個欄位需要唯一標識,則既可以使用@Column標記也可以使用@Table標記中的@UniqueConstraint。

  (2)nullable 屬性表示該欄位是否可以為null值,預設為true(允許為null值)。

  (3)insertable 屬性表示在使用“INSERT” SQL語指令碼插入資料時,是否需要插入該欄位的值。

  (4)updatable 屬性表示在使用“UPDATE”指令碼插入資料時,是否需要更新該欄位的值。insertable和updatable屬性一般多用於只讀屬性,例如主鍵和外來鍵等。這些欄位值通常是自動生成的。

  (5)columnDefinition 屬性表示建立表時,該欄位建立的SQL語句,一般用於通過Entity生成表定義時使用。

  (6)table 屬性表示當對映多個表時,指定表中的欄位。預設值為主表的表名。

  (7)length 屬性表示該欄位的長度,當欄位的型別為varchar時,該屬性才有效,預設為255個字元。

  (8)precision 屬性和scale 屬性表示精度,當欄位型別為double時,precision表示數值的總長度,scale表示小數點所佔的位數。

示例一、

Java程式碼  收藏程式碼
  1. private String name;  
  2. @Column(name = “name”,nullable=false,length=512)  
  3. public String getName() {  
  4.     return name;  
  5. }  

 生成的SQL指令碼為

Java程式碼  收藏程式碼
  1. CREATE TABLE contact(  
  2.       id integer not null,  
  3.       name varchar(512) not null,  
  4.       primary key(id)  
  5. );  

  示例二、為double型指定精度為12位,小數點位數為2位。

Java程式碼  收藏程式碼
  1. private BigDecimal monthlyIncome;  
  2. @Column(name=“monthly_income”,precision=12,scale=2)  
  3. public BigDecimal getMonthlyIncome() {  
  4.     return monthlyIncome;  
  5. }  
  6. public void setMonthlyIncome(BigDecimal monthlyIncome) {  
  7.     this.monthlyIncome = monthlyIncome;  
  8. }  

 生成的SQL指令碼為

Java程式碼  收藏程式碼
  1. CREATE TABLE contact(  
  2.       id integer not null,  
  3.       monthly_income double(12,2),  
  4.       primary key(id)  
  5. );  

 示例三、自定義生成CLOB型別欄位的SQL語句

Java程式碼  收藏程式碼
  1. @Column(name = “contact_name”,columnDefinition=“ clob not null” )  
  2. private String name;  
  3. public String getName() {  
  4.     return name;  
  5. }  
  6. public void setName(String name) {  
  7.     this.name = name;  
  8. }  

  生成的SQL指令碼為

Sql程式碼  收藏程式碼
  1. CREATE TABLE contact(  
  2.       id integer not null,  
  3.       contact_name <strong>clob(200) not null,</strong>  
  4.       primary key(id)  
  5. );  

  其中加粗的部份為columnDefinition屬性設定的值。若不指定該屬笥,通常使用預設的型別建表,若此時需要自定義建表的型別時,可以在該屬性設定。

可持久化的資料型別

分類 型別
Java的基本資料型別 byte、int、short、long、boolean、char、float、double
Java的基本資料型別對應的封裝類 Byte、Int、Short、Long、Boolean、Character、Float、Double
位元組和字元型陣列 byte[]、Byte[]、char[]、Character[]
大數值型別

Java.math.BigInteger

java.math.BigDecimal
字串型別 java.lang.String
日期時間型別

java.util.Date

java.util.Calendar

java.sql.Date

java.sql.Time

java.sql.Timestamp
列舉型 使用者自定義的列舉型
Entity型別 標註為@Entity的類
包含Entity型別的集合Collection類

java.util.Collection

java.util.Set

java.util.List

java.util.Map
嵌入式(embeddable)類

 Java資料型別與資料庫中的型別轉換是由JPA實現框架自動轉換的,所以不同的JPA實現框架轉換的規則也不太一樣。

     例如MySQL中,varchar和char型別都轉化為String型別。Blob和Clob型別可以轉化成Byte[]型。由於型別轉化是JPA底層來實現的,這就遇到一個問題,很有可能在將表中的資料轉換成Java的資料型別時出現異常。

       我們知道對於可以持久化的Java型別中,即可以對映基本的資料型別,如byte、int、short、long、boolean、char、float、double等,也可以對映成 Byte、Int、Short、Long、Boolean、Character、Float、 Double型別。那麼選擇哪種型別比較合適呢?

舉下面的例子進行說明。

Sql程式碼  收藏程式碼
  1. CREATE TABLE contact(  
  2.       id integer not null,  
  3.       monthly_income double(12,2),  
  4.       primary key(id)  
  5. );  

      對於表字段id,它的值不能為null,所以對映成int型和Integer型都是可以的。

      但對於表字段monthly_income來說,它的值可能為null。當為null時,若此時java的Enity類的對應屬性的型別int,則將一個null值轉化成int型必定產生轉換異。但此時java的Entity類對應的屬性為Integer,它是一個物件,物件可以為null,所以不會產生問題。

4、@Basic

    在預設情況下,Entity中屬笥載入方式都是即時載入(EAGER)的,當Enity物件例項化時,就加截了實體中相應的屬性值。

    但對於一些特殊屬笥,比如大文字型text、位元組流型blob型的資料,在載入Entity時,這些屬性對應的資料量比較大,有時建立實體時如果也載入的話,可能造成資源嚴重佔用。那麼就可以為這些特殊的實體屬性設定載入方式為惰性載入(LAZY)

   (1)fetch屬性表示獲取值的方式,它的值定義的列舉型,可選值為LAZY、EAGER。其中EAGER表示即時載入、LAZY表示惰性載入。預設為即時載入。

   (2)optional表示屬性是否可以為null,不能用於java基本資料型( byte、int、short、long、boolean、char、float、double )。

如:

Java程式碼  收藏程式碼
  1. @Basic(fetch=FetchType.LAZY)  
  2. @Column(name = “contact_name”,columnDefinition=“ clob not null” )  
  3. private String name;  
  4. public String getName() {  
  5.     return name;  
  6. }  
  7. public void setName(String name) {  
  8.     this.name = name;  
  9. }  

5、@Id

       主鍵是實體的唯一標識,呼叫EntityManager的find方法,可以獲得相應的實體物件。每一個實體類至少要有一個主鍵(Primary key)。

       一旦使用@Id 標記屬性為主鍵,該實體屬性的值可以指定,也可以根據一些特定的規則自動生成。這就涉及另一個標記@GeneratedValue 的使用。

@GeneratedValue 標註有以兩個屬性:

(1)strategy 屬性表示生成主鍵的策略 ,有4種類型,分別定義在列舉型GenerationType中,其中有GenerationType.TABLE 、 GenerationType.SEQUENCE  GenerationType.IDENTITY  GenerationType.AUTO ,其中,預設為AUTO,表示自動生成。

(2)generator 為不同策略型別所對應的生成規則名,它的值根據不同的策略有不同的設定。

(3)能夠標識為主鍵的屬性型別,有如表5-2所列舉的幾種。

分類 型別
Java的基本資料型別 byte、int、short、long、char
Java的基本資料型別對應的封裝類 Byte、Integer、Short、Long、Character
大數值型別 java.math.BigInteger
字串型別 java.lang.String
時間日期型 java.util.Date
java.sql.Date

double和float浮點型別和它們對應的封裝類不能作為主鍵,這是因為判斷是否唯一是通過equals方法來判斷的,浮點型的精度太大,不能夠準確地匹配。

例一,自增主鍵 。在不同的資料庫,自增主鍵的生成策略可能有所不同。例如MySQL的自增主鍵可以通過IDENTITY來實現,而Oracle可能需要建立Sequence來實現自增。JPA的實現將會根據不同的資料庫型別來實現自增的策略。

Java程式碼  收藏程式碼
  1. @Id  
  2. @GeneratedValue(strategy = GenerationType.AUTO)  
  3. public Long getId() {  
  4.     return id;  
  5. }  
  6. public void setId(Long id) {  
  7.     this.id = id;  
  8. }  

 例二,表生成器 。將當前主鍵的值單獨儲存到一個數據庫的表中,主鍵的值每次都是從指定的表中查詢來獲得,這種生成主鍵的方式也是很常用的。這種方法生成主鍵的策略可以適用於任何的資料庫,不必擔心與同資料庫不相容造成問題。

         配置的Customer類

Java程式碼  收藏程式碼
  1. package model;  
  2. import java.io.Serializable;  
  3. import javax.persistence.Basic;  
  4. import javax.persistence.Column;  
  5. import javax.persistence.Entity;  
  6. import javax.persistence.GeneratedValue;  
  7. import javax.persistence.GenerationType;  
  8. import javax.persistence.Id;  
  9. import javax.persistence.Table;  
  10. import javax.persistence.TableGenerator;  
  11. @Entity  
  12. @Table(schema = “open_jpa”, name = “customer”)  
  13. public class Customer implements Serializable  
  14. {  
  15.     private static final long serialVersionUID = -8480590552153589674L;  
  16.     private Integer           id;  
  17.     private String            name;  
  18.     @Id  
  19.     @GeneratedValue(strategy = GenerationType.TABLE, generator = “customer_gen”)  
  20.     @TableGenerator(schema = “open_jpa”,   
  21.             name = ”customer_gen”,   
  22.             table = ”tbl_generator”,   
  23.             pkColumnName = ”gen_name”,   
  24.             pkColumnValue = ”CUSTOMER_PK”,   
  25.             valueColumnName = ”gen_value”,   
  26.             allocationSize = 1,   
  27.             initialValue = 0)  
  28.     public Integer getId()  
  29.     {  
  30.         return id;  
  31.     }  
  32.     public void setId(Integer id)  
  33.     {  
  34.         this.id = id;  
  35.     }  
  36.     @Basic  
  37.     @Column(name = “name”)  
  38.     public String getName()  
  39.     {  
  40.         return name;  
  41.     }  
  42.     public void setName(String name)  
  43.     {  
  44.         this.name = name;  
  45.     }  
  46. }  

 (1)在Entity標記的主鍵的位置,指定主鍵生成策略為“GenerationType.TABLE ”。

 (2)指定生成主鍵策略的名稱,例如這裡命名為“generator = “customer_gen” ”。

 (3)使用@TableGenerator標定義表生成策略的具體設定:

Java程式碼  收藏程式碼
  1. @TableGenerator(schema = “open_jpa”,   
  2.            name = ”customer_gen”,   
  3.            table = ”tbl_generator”,   
  4.            pkColumnName = ”gen_name”,   
  5.            pkColumnValue = ”CUSTOMER_PK”,   
  6.            valueColumnName = ”gen_value”,   
  7.            allocationSize = 1,   
  8.            initialValue = 0)  

 可以看到資料生成tbl_generator 的結構及新增的資料:

Sql程式碼  收藏程式碼
  1. CREATE TABLE `tbl_generator` (  
  2.   `GEN_NAME` varchar(255) NOT NULL,  
  3.   `GEN_VALUE` bigint(20) default NULL,  
  4.   PRIMARY KEY  (`GEN_NAME`)  
  5. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  6. INSERT INTO tbl_generator VALUES (‘CUSTOMER_PK’, 1);  

使用Oracle的sequence方式生成ID值。  

Java程式碼  收藏程式碼
  1. @Id    
  2. @GeneratedValue(strategy = GenerationType.SEQUENCE,generator=“payablemoney_seq”)    
  3. @SequenceGenerator(name=“payablemoney_seq”, sequenceName=“seq_payment”)    

@SequenceGenerator定義

Java程式碼  收藏程式碼
  1. @Target({TYPE, METHOD, FIELD})     
  2. @Retention(RUNTIME)    
  3. public @interface SequenceGenerator {    
  4.  String name();    
  5.  String sequenceName() default “”;    
  6.  int initialValue() default 0;    
  7.  int allocationSize() default 50;    
  8. }   

 name屬性表示該表主鍵生成策略的名稱,它被引用在@GeneratedValue中設定的“generator”值中。 
sequenceName屬性表示生成策略用到的資料庫序列名稱。 
initialValue表示主鍵初識值,預設為0。 
allocationSize表示每次主鍵值增加的大小,例如設定成1,則表示每次建立新記錄後自動加1,預設為50。