<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-179  評論-666  文章-29  trackbacks-0

    數(shù)據(jù)的唯一性是所有應(yīng)用程序非常基本的要求,由開發(fā)者或者用戶來維護(hù)這種唯一性存在著較大的風(fēng)險(xiǎn),因此,由系統(tǒng)自動(dòng)產(chǎn)生唯一標(biāo)識是一種常見的做法。OpenJPA 中支持四種不同的實(shí)體標(biāo)識自動(dòng)生成策略:

    • 容器自動(dòng)生成的實(shí)體標(biāo)識;
    • 使用數(shù)據(jù)庫的自動(dòng)增長字段生成實(shí)體標(biāo)識;
    • 根據(jù)數(shù)據(jù)庫序列號(Sequence)技術(shù)生成實(shí)體標(biāo)識;
    • 使用數(shù)據(jù)庫表的字段生成實(shí)體標(biāo)識;

    這四種方式各有優(yōu)缺點(diǎn),開發(fā)者可以根據(jù)實(shí)際情況進(jìn)行選擇。

    可選擇的注釋

    要讓容器和數(shù)據(jù)庫結(jié)合管理實(shí)體標(biāo)識的自動(dòng)生成,根據(jù)實(shí)際情況的不同,開發(fā)者可以選擇 javax.persistence.*包下面的 GeneratedValueSequenceGeneratorTableGenerator三個(gè)注釋來描述實(shí)體的標(biāo)識字段。

    @javax.persistence.GeneratedValue

    每一個(gè)需要自動(dòng)生成實(shí)體標(biāo)識的實(shí)體都需要為它的實(shí)體標(biāo)識字段提供 GeneratedValue注釋和相應(yīng)的參數(shù),OpenJPA 框架會根據(jù)注釋和參數(shù)來處理實(shí)體標(biāo)識的自動(dòng)生成。

    使用 GeneratedValue注釋自動(dòng)生成的實(shí)體標(biāo)識可以是數(shù)值類型字段如 byte、short、intlong等,或者它們對應(yīng)的包裝器類型 ByteShort、Integer、Long等,也可以是字符串類型。

    GeneratedValue注釋可以支持兩個(gè)屬性 strategygenerator。

    • strategy

      strategyGenerationType類型的枚舉值,它的內(nèi)容將指定 OpenJPA 容器自動(dòng)生成實(shí)體標(biāo)識的方式。strategy屬性可以是下列枚舉值:

      • GeneratorType.AUTO

        表示實(shí)體標(biāo)識由 OpenJPA 容器自動(dòng)生成,這也是 Strategy 屬性的默認(rèn)值。

      • GenerationType.IDENTITY

        OpenJPA 容器將使用數(shù)據(jù)庫的自增長字段為新增加的實(shí)體對象賦唯一值,作為實(shí)體的標(biāo)識。這種情況下需要數(shù)據(jù)庫提供對自增長字段的支持,常用的數(shù)據(jù)庫中,HSQL、SQL Server、MySQL、DB2、Derby 等數(shù)據(jù)庫都能夠提供這種支持。

      • GenerationType.SEQUENCE

        表示使用數(shù)據(jù)庫的序列號為新增加的實(shí)體對象賦唯一值,作為實(shí)體的標(biāo)識。這種情況下需要數(shù)據(jù)庫提供對序列號的支持,常用的數(shù)據(jù)庫中,Oracle、PostgreSQL 等數(shù)據(jù)庫都能夠提供這種支持。

      • GenerationType.TABLE

        表示使用數(shù)據(jù)庫中指定表的某個(gè)字段記錄實(shí)體對象的標(biāo)識,通過該字段的增長為新增加的實(shí)體對象賦唯一值,作為實(shí)體的標(biāo)識。

    • String generator

      generator屬性中定義實(shí)體標(biāo)識生成器的名稱。如果實(shí)體的標(biāo)識自動(dòng)生成策略不是 GenerationType.AUTO或者 GenerationType.IDENTITY,就需要提供相應(yīng)的 SequenceGenerator或者 TableGenerator注釋,然后將 generator屬性值設(shè)置為注釋的 name屬性值。

    @javax.persistence.SequenceGenerator

    如果實(shí)體標(biāo)識的自動(dòng)生策略是 GenerationType.SEQUENCE,開發(fā)者需要為實(shí)體標(biāo)識字段提供 SequenceGenerator注釋,它的參數(shù)描述了使用序列號生成實(shí)體標(biāo)識的具體細(xì)節(jié)。該注釋支持以下四個(gè)屬性:


    表 1. SequenceGenerator 注釋屬性說明
    屬性 說明
    name 該屬性是必須設(shè)置的屬性,它表示了 SequenceGenerator注釋在 OpenJPA 容器中的唯一名稱,將會被 GeneratedValue注釋的 generator屬性使用。將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫的序列號特性時(shí),實(shí)體標(biāo)識字段的 GeneratedValue注釋的 generator屬性的值必須和某個(gè) SequenceGenerator注釋的 name屬性值保持一致。
    sequenceName 實(shí)體標(biāo)識所使用的數(shù)據(jù)庫序列號的名稱。該屬性是可選的,如果我們沒有為該屬性設(shè)置值,OpenJPA 框架將自動(dòng)創(chuàng)建名為 OPENJPA_SEQUENCE的序列號。如果一個(gè) OpenJPA 容器中管理的多個(gè)實(shí)體都選擇使用序列號機(jī)制生成實(shí)體標(biāo)識,而且實(shí)體類中都沒有指定標(biāo)識字段的 sequenceName屬性,那么這些實(shí)體將會共享系統(tǒng)提供的默認(rèn)名為 OPENJPA_SEQUENCE的序列號。這可能引起實(shí)體類編號的不連續(xù)。我們可以用下面的這個(gè)簡單例子說明這種情況:假設(shè) OpenJPA 容器中存在兩個(gè)實(shí)體類 Dog 和 Fish,它們的實(shí)體標(biāo)識字段都是數(shù)值型,并且都選擇使用序列號生成實(shí)體標(biāo)識,但是實(shí)體類中并沒有提供 sequenceName屬性值。當(dāng)我們首先持久化一個(gè) Dog 對象時(shí),它的實(shí)體標(biāo)識將會是 1,緊接著我們持久化一個(gè) Fish 對象,它的實(shí)體標(biāo)識就是 2,依次類推。
    initialValue 該屬性設(shè)置所使用序列號的起始值。
    allocationSize 一些數(shù)據(jù)庫的序列化機(jī)制允許預(yù)先分配序列號,比如 Oracle,這種預(yù)先分配機(jī)制可以一次性生成多個(gè)序列號,然后放在 cache 中,數(shù)據(jù)庫用戶獲取的序列號是從序列號 cache 中獲取的,這樣就避免了在每一次數(shù)據(jù)庫用戶獲取序列號的時(shí)候都要重新生成序列號。allocationSize屬性設(shè)置的就是一次預(yù)先分配序列號的數(shù)目,默認(rèn)情況下 allocationSize屬性的值是 50。

    @javax.persistence.TableGenerator

    如果實(shí)體標(biāo)識的自動(dòng)生策略是 GenerationType.TABLE,開發(fā)者需要為實(shí)體標(biāo)識字段提供 TableGenerator 注釋,它的參數(shù)描述了使用數(shù)據(jù)庫表生成實(shí)體標(biāo)識的具體細(xì)節(jié)。該注釋支持下列屬性:


    表 2. TableGenerator 注釋屬性說明
    屬性 說明
    name 該屬性是必須設(shè)置的屬性,它表示了 TableGenerator注釋在 OpenJPA 容器中的唯一名稱,將會被 GeneratedValue注釋的 generator屬性所使用。將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫表時(shí),實(shí)體標(biāo)識字段的 GeneratedValue注釋的 generator屬性的值必須和某個(gè) TableGenerator注釋的 name屬性值保持一致。
    table 該屬性設(shè)置的是生成序列號的表的名稱。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)的表名 OPENJPA_SEQUENCES_TABLE
    schema 該屬性設(shè)置的是生成序列號的表的 schema。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會默認(rèn)使用當(dāng)前數(shù)據(jù)庫用戶對應(yīng)的 schema。
    catalog 該屬性設(shè)置的是生成序列號的表的 catalog。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)當(dāng)前數(shù)據(jù)庫用戶對應(yīng)的 catalog。
    pkColumnName 該屬性設(shè)置的是生成序列號的表中的主鍵字段的名稱,該字段將保存代表每個(gè)實(shí)體對應(yīng)的標(biāo)識值對應(yīng)的特征字符串。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)值 ID。
    valueColumnName 該屬性設(shè)置的是生成序列號的表中記錄實(shí)體對應(yīng)標(biāo)識最大值的字段的名稱。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該 屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)值 SEQUENCE_VALUE。
    pkColumnValue 該屬性設(shè)置的是生成序列號的表中的主鍵字段的特征字符串值 ( 比如 customID ),該字段將保存代表每個(gè)實(shí)體對應(yīng)的標(biāo)識值對應(yīng)的特征字符串。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)值 DEFAULT。可以為多個(gè)實(shí)體設(shè)置相同的 pkColumnValue屬性值,這些實(shí)體標(biāo)識的生成將通過同一列的值的遞增來實(shí)現(xiàn)。
    initialValue 該屬性設(shè)置的是生成序列號的表實(shí)體標(biāo)識的初始值。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)值 0 。
    allocationSize 為了降低標(biāo)識生成時(shí)頻繁操作數(shù)據(jù)庫造成 的性能上的影響,實(shí)體標(biāo)識生成的時(shí)候會一次性的獲取多個(gè)實(shí)體標(biāo)識,該屬性設(shè)置的就是一次性獲取實(shí)體標(biāo)識的數(shù)目。該屬性并不是必須設(shè)置的屬性,如果開發(fā)者沒有為該屬性設(shè)置值,OpenJPA 容器將會使用默認(rèn)值 50 。

    實(shí)體標(biāo)識自動(dòng)生成

    在上面的小節(jié)中,我們了解了和實(shí)體標(biāo)識自動(dòng)生成相關(guān)的注釋,接下來我們將結(jié)合一個(gè)簡單的例子講述如何分別使用這些實(shí)體標(biāo)識自動(dòng)生成策略實(shí)現(xiàn)實(shí)體標(biāo)識的自動(dòng)生成。

    我們首先假設(shè)有一個(gè) Animal實(shí)體需要被持久化,它包括 IDNAME屬性,其中 ID是它的主鍵字段。Animal實(shí)體的標(biāo)識需要自動(dòng)生成,我們將分析在這四種不用的情況下,如何使用 OpenJPA 提供的注釋,結(jié)合具體數(shù)據(jù)庫支持的特性,如自增長字段、序列號等來實(shí)現(xiàn)實(shí)體標(biāo)識的自動(dòng)生成。

    容器自動(dòng)生成

    OpenJPA 容器默認(rèn)的實(shí)體標(biāo)識自動(dòng)生成策略是由容器管理實(shí)體標(biāo)識的自動(dòng)生成,容器管理的實(shí)體標(biāo)識可以支持?jǐn)?shù)值型和字符型兩種。當(dāng)容器管理的實(shí)體標(biāo)識是數(shù)字型時(shí),OpenJPA 容器自動(dòng)創(chuàng)建一個(gè)數(shù)據(jù)庫表 OPENJPA_SEQUENCE_TABLE,用其中的 SEQUENCE_VALUE字段來記錄實(shí)體的實(shí)體標(biāo)識的增長。

    當(dāng)容器管理的實(shí)體標(biāo)識是字符串類型時(shí),OpenJPA 支持使用 uuid-string 和 uuid-hex 兩種方式生成相應(yīng)的實(shí)體標(biāo)識。如果我們選擇使用 uuid-string 方式生成實(shí)體標(biāo)識時(shí),OpenJPA 框架會自動(dòng)為實(shí)體生成一個(gè) 128 位的 UUID,并且將這個(gè) UUID 轉(zhuǎn)化為使用 16 位字符表示的字符串。如果我們選擇使用 uuid-hex 方式生成實(shí)體標(biāo)識時(shí),OpenJPA 框架會自動(dòng)為實(shí)體生成一個(gè) 128 位的 UUID,并且將這個(gè) UUID 轉(zhuǎn)化為使用 32 位字符表示的 16 進(jìn)制的字符串。

    數(shù)值標(biāo)識

    容器管理的實(shí)體標(biāo)識可以是數(shù)值型的,OpenJPA 框架管理的實(shí)體標(biāo)識借助于數(shù)據(jù)庫的表來實(shí)現(xiàn),在運(yùn)行時(shí) OpenJPA 框架會自動(dòng)在數(shù)據(jù)庫中創(chuàng)建表 OPENJPA_SEQUENCE_TABLE。它有兩個(gè)字段:IDSEQUENCE_VALUE,這兩個(gè)字段都是數(shù)值類型,其中 ID是表的主鍵字段,它的內(nèi)容是查詢當(dāng)前實(shí)體標(biāo)識時(shí)所使用的關(guān)鍵詞,默認(rèn)值是 0。而 SEQUENCE_VALUE記錄了當(dāng)前 OpenJPA 框架中當(dāng)前實(shí)體標(biāo)識的歷史數(shù)據(jù),內(nèi)容是已經(jīng)被獲取實(shí)體標(biāo)識的最大數(shù)值加 1。

    我們要使用注釋描述 Animal實(shí)體的標(biāo)識由容器自動(dòng)生成,只需要為它的標(biāo)識字段提供 GeneratedValue注釋,并且把它的 strategy屬性設(shè)置為 GenerationType.AUTO, Animal實(shí)體類的代碼片斷如下:


    清單 1. 標(biāo)識由容器自動(dòng)生成的 Animal 實(shí)體類
                1. 	 import javax.persistence.Entity;
                2. 	 import javax.persistence.GeneratedValue;
                3. 	 import javax.persistence.GenerationType;
                4. 	 import javax.persistence.Id;
                5.
                6. 	 @Entity
                7. 	 public class Animal {
                8. 		 @Id
                9. 		 @GeneratedValue(strategy=GenerationType.AUTO)
                10. 		 private long id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    保存 Animal實(shí)體的第一個(gè)實(shí)例時(shí),OpenJPA 框架自動(dòng)調(diào)用 SQL 語句 SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID=0,從默認(rèn)保存實(shí)體標(biāo)識的 OPENJPA_SEQUENCE_TABLE表中獲取實(shí)體的標(biāo)識,如果不存在 ID為 0 的記錄,OpenJPA 框架自動(dòng)將實(shí)體的標(biāo)識設(shè)置為 1。

    容器管理實(shí)體標(biāo)識的情況下,為了獲得實(shí)體標(biāo)識,應(yīng)用程序?qū)⒉坏貌活l繁地和數(shù)據(jù)庫交互,這會影響應(yīng)用程序的運(yùn)行效率。OpenJPA 中使用實(shí)體標(biāo)識緩存機(jī)制解決這個(gè)問題。默認(rèn)情況下,當(dāng)應(yīng)用程序第一次獲取實(shí)體標(biāo)識時(shí),OpenJPA 框架從數(shù)據(jù)庫中一次性獲取 50 個(gè)連續(xù)的實(shí)體標(biāo)識緩存起來,當(dāng)下一次應(yīng)用程序需要獲取實(shí)體標(biāo)識時(shí),OpenJPA 將首先檢測緩存中是否存在實(shí)體標(biāo)識,如果存在,OpenJPA 將直接使用緩存中的實(shí)體標(biāo)識,如果不存在,OpenJPA 框架將會從數(shù)據(jù)庫中再次獲取 50 個(gè)連續(xù)的實(shí)體標(biāo)識緩存起來,如此類推。這樣的處理方式可以大大減少由于獲取實(shí)體標(biāo)識而產(chǎn)生的數(shù)據(jù)庫交互,提升應(yīng)用程序的運(yùn)行效率。

    當(dāng)實(shí)體標(biāo)識成功獲取之后,OpenJPA 框架會把當(dāng)前實(shí)體標(biāo)識的最大值 +1 后持久化到數(shù)據(jù)庫中。由于實(shí)體標(biāo)識緩存的原因,當(dāng)我們第一次獲取實(shí)體標(biāo)識后,OpenJPA 會將 OPENJPA_SEQUENCE_TABLE表的 SEQUENCE_VALUE的值設(shè)置為 51,當(dāng) OpenJPA 多次從數(shù)據(jù)庫中獲取實(shí)體標(biāo)識后,SEQUENCE_VALUE的值會以 50 為單位遞增,變?yōu)?101、151、201 …。

    OpenJPA 緩存的實(shí)體標(biāo)識不是永久存在的,只能在同一個(gè) EntityManagerFactory管理范圍內(nèi)起作用,也就是說,當(dāng)獲取實(shí)體標(biāo)識的 EntityManagerFactory對象被關(guān)閉后,這些被獲取的實(shí)體標(biāo)識中沒有用掉的那一部分標(biāo)識就丟失了,這會造成實(shí)體標(biāo)識的不連續(xù)。由同一個(gè) EntityManagerFactory對象創(chuàng)建的 EntityManager上下文之間則能夠共享 OpenJPA 框架獲取的實(shí)體標(biāo)識,這意味著,我們可以使用同一個(gè) EntityManagerFactory對象創(chuàng)建多個(gè) EntityManager對象,用它來持久化實(shí)體,然后關(guān)閉它,在持久化過程中所需要的實(shí)體表示將會使用同一個(gè)實(shí)體標(biāo)識的緩存區(qū),因此不會引起實(shí)體標(biāo)識的丟失。

    容器管理的實(shí)體標(biāo)識還有一個(gè)非常重要的特性:所有被容器管理的實(shí)體標(biāo)識都是共享的。不管 OpenJPA 容器中存在多少個(gè)不同的被容器管理的實(shí)體標(biāo)識,它們都會從同一個(gè)實(shí)體標(biāo)識緩存中獲取實(shí)體標(biāo)識。我們可以用下面的例子說明這種情況:假設(shè) OpenJPA 容器中存在兩個(gè)實(shí)體類 DogFish,它們的實(shí)體標(biāo)識字段都是數(shù)值型,并且都由 OpenJPA 管理。當(dāng)我們首先持久化一個(gè) Dog對象時(shí),它的實(shí)體標(biāo)識將會是 1,緊接著我們持久化一個(gè) Fish對象,它的實(shí)體標(biāo)識就是 2,依次類推。

    uuid-string

    要使用 uuid-string 機(jī)制自動(dòng)生成實(shí)體標(biāo)識,我們需要將實(shí)體主鍵字段的 GeneratedValue注釋的 strategy屬性設(shè)置為 GenarationType.AUTO,然后將 GeneratedValue注釋的 generator屬性設(shè)置為 uuid-string。以 Animal 實(shí)體類為例,我們只需要將 Animal 實(shí)體修改為如下內(nèi)容:


    清單 2. 使用 uuid-string 機(jī)制自動(dòng)生成實(shí)體標(biāo)識
                1. 	 import javax.persistence.Entity;
                2. 	 import javax.persistence.GeneratedValue;
                3. 	 import javax.persistence.GenerationType;
                4. 	 import javax.persistence.Id;
                5.
                6. 	 @Entity
                7. 	 public class Animal {
                8. 		 @Id
                9. 		 @GeneratedValue(strategy=GenerationType.AUTO, generator = "uuid-string")
                10. 		 private String id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    uuid-hex

    要使用 uuid-hex 機(jī)制自動(dòng)生成實(shí)體標(biāo)識,我們必須將實(shí)體主鍵字段的 GeneratedValue注釋的 strategy屬性設(shè)置為 GenarationType.AUTO,然后將 GeneratedValue注釋的 generator屬性設(shè)置為 uuid-hex。以 Animal 實(shí)體類為例,我們只需要將 Animal 實(shí)體修改為如下內(nèi)容:


    清單 3. 使用 uuid-hex 機(jī)制自動(dòng)生成實(shí)體標(biāo)識
                1. 	 import javax.persistence.Entity;
                2. 	 import javax.persistence.GeneratedValue;
                3. 	 import javax.persistence.GenerationType;
                4. 	 import javax.persistence.Id;
                5.
                6. 	 @Entity
                7. 	 public class Animal {
                8. 		 @Id
                9. 		 @GeneratedValue(strategy=GenerationType.AUTO, generator = "uuid-hex")
                10. 		 private String id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    自增長字段

    自增長字段是 HSQL、SQL Server、MySQL、DB2、Derby 等數(shù)據(jù)庫提供的一種特性,用于為數(shù)據(jù)庫的記錄提供自動(dòng)增長的編號,應(yīng)用程序的設(shè)計(jì)者通常期望將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫的這種特性,OpenJPA 框架中的實(shí)體標(biāo)識能夠滿足應(yīng)用程序設(shè)計(jì)者的要求,使用數(shù)據(jù)庫的自增長字段為實(shí)體自動(dòng)生成標(biāo)識。

    要將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫的自增長字段特性,需要數(shù)據(jù)庫和實(shí)體定義的雙方配合才能夠達(dá)到:首先,必須將實(shí)體標(biāo)識字段對應(yīng)的數(shù)據(jù)庫列修改為自動(dòng)增長列,另外還需要將實(shí)體類中實(shí)體標(biāo)識字段的 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.IDENTITY

    我們以 Animal 實(shí)體在 HSQL 數(shù)據(jù)庫中的持久化來說明如何使用自增長字段自動(dòng)生成實(shí)體標(biāo)識所需要采取的步驟:

    首先,我們使用下面的 SQL 語句創(chuàng)建 Animal 表,把它的 ID字段設(shè)置為自動(dòng)增長類型:


    清單 4. 將 ID 字段設(shè)置為自動(dòng)增長類型的 SQL 語句
                CREATE TEXT TABLE ANIMAL (
                ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,
                NAME VARCHAR(255) NOT NULL
                )
                

    在數(shù)據(jù)庫部分將表的主鍵字段設(shè)置為自動(dòng)增長字段后,在實(shí)體 Animal的定義中,我們需要將 id字段 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.IDENTITY。Animal 實(shí)體類修改后的代碼片段如下。


    清單 5. 標(biāo)識由自增長字段生成的 Animal 實(shí)體類
                1. 	 import javax.persistence.Entity;
                2. 	 import javax.persistence.GeneratedValue;
                3. 	 import javax.persistence.GenerationType;
                4. 	 import javax.persistence.Id;
                5.
                6. 	 @Entity
                7. 	 public class Animal {
                8. 		 @Id
                9. 		 @GeneratedValue(strategy=GenerationType.IDENTITY)
                10. 		 private long id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    序列號(Sequence)

    序列號是 Oracle、PostgreSQL 等數(shù)據(jù)庫提供的一種特性,用于為數(shù)據(jù)庫的記錄提供自動(dòng)增長的編號,使用 Oracle、PostgreSQL 等數(shù)據(jù)庫應(yīng)用程序的設(shè)計(jì)者通常期望將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫的這種特性,OpenJPA 框架中的實(shí)體標(biāo)識能夠滿足應(yīng)用程序設(shè)計(jì)者的要求,使用數(shù)據(jù)庫的序列號為實(shí)體自動(dòng)生成標(biāo)識。

    要將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫的序列號特性,需要數(shù)據(jù)庫和實(shí)體定義的雙方配合才能夠達(dá)到:首先,必須在數(shù)據(jù)庫中創(chuàng)建合適的序列號,另外還需要為實(shí)體標(biāo)識字段提供 SequenceGenerator注釋,設(shè)置它的參數(shù),為實(shí)體類提供關(guān)于序列號的信息,同時(shí)將實(shí)體類中實(shí)體標(biāo)識字段的 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.SEQUENCE,將 generator屬性的值設(shè)置為 SequenceGenerator注釋的 name屬性的值。

    我們以 Animal 實(shí)體在 Oracle 數(shù)據(jù)庫中的持久化來說明如何使用自增長字段自動(dòng)生成實(shí)體標(biāo)識所需要采取的步驟:

    首先,在 Oracle 數(shù)據(jù)庫中運(yùn)行下面的 SQL 語句創(chuàng)建名為 HelloWorldSequence的序列號,序列號支持 cache,大小為 50:


    清單 6. 創(chuàng)建序列號的 SQL 語句
                CREATE SEQUENCE HELLOWORLDSEQUENCE
                START WITH 0
                INCREMENT BY 1
                MINVALUE 1
                CACHE 50
                NOCYCLE
                NOORDER
                

    然后,在 Oracle 數(shù)據(jù)庫中,我們使用下面的 SQL 語句創(chuàng)建 ANIMAL表:


    清單 7. 創(chuàng)建 ANIMAL 表
                CREATE TABLE EOS52.ANIMAL
                (
                ID CHAR(10),
                NAME VARCHAR2(100) NOT NULL,
                CONSTRAINT PK_ANIMAL PRIMARY KEY (ID )
                )
                

    在數(shù)據(jù)庫部分創(chuàng)建合適的序列號和相應(yīng)的數(shù)據(jù)庫表后,在實(shí)體 Animal的定義中,我們需要將 id字段 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.SEQUENCE,設(shè)置它的 generator屬性的值為 SeqGenerator。我們還需要為 id字段提供另外一個(gè)相關(guān)的注釋 SequenceGenerator,設(shè)置它的 name屬性為 SeqGenerator,設(shè)置它 sequenceName屬性為 HelloWorldSequence。Animal 實(shí)體類修改后的代碼片段如下。


    清單 8. 標(biāo)識由序列號生成的 Animal 實(shí)體類
                1.  import javax.persistence.Entity;
                2.  import javax.persistence.GeneratedValue;
                3.  import javax.persistence.GenerationType;
                4.  import javax.persistence.Id;
                5.
                6.  @Entity
                7.  public class Animal {
                8.      @Id
                9.      @GeneratedValue(strategy = GenerationType.SEQUENCE,
                generator = "SeqGenerator")
                10.     @SequenceGenerator(name = "SeqGenerator",
                sequenceName = " HelloWorldSequence")
                11.     private long id;
                12.     private String name;
                13.
                14.     …
                15.
                16. }
                

    數(shù)據(jù)庫表

    除了使用容器生成的實(shí)體標(biāo)識,或者借助于數(shù)據(jù)庫的自增長字段或者序列號等方式生成實(shí)體標(biāo)識之外,我們還可以選擇借助數(shù)據(jù)庫表來自動(dòng)生成實(shí)體標(biāo)識。原理是我們提供一個(gè)獨(dú)立的數(shù)據(jù)庫表,該表的主鍵列 ( 假設(shè)列名 ID) 記錄實(shí)體編號的特征字符串 ( 假設(shè)存在一條記錄的 IDcustomID),另外一列 ( 假設(shè)列名為 SEQUENCE_VALUE) 記錄該特征字符串對應(yīng)實(shí)體標(biāo)識的最大值。編寫實(shí)體代碼時(shí),我們指定實(shí)體標(biāo)識由數(shù)據(jù)庫表中指定的特征字符串 ( 如 customID) 對應(yīng)的列 SEQUENCE_VALUE處理,當(dāng)有新的實(shí)體被持久化時(shí),容器將獲取行 customID、列 SEQUENCE_VALUE對應(yīng)的數(shù)值 +1 后作為新實(shí)體的標(biāo)識,同時(shí)將該列的值也自動(dòng) +1。

    要將實(shí)體標(biāo)識的自動(dòng)生成委托給數(shù)據(jù)庫表,需要數(shù)據(jù)庫和實(shí)體定義的雙方配合才能夠達(dá)到:首先,必須在數(shù)據(jù)庫中創(chuàng)建合適的保存實(shí)體標(biāo)識的表,另外還需要為實(shí)體標(biāo)識字段提供 TableGenerator注釋,設(shè)置它的參數(shù),為實(shí)體類提供關(guān)于數(shù)據(jù)庫表、字段的信息,同時(shí)將實(shí)體類中實(shí)體標(biāo)識字段的 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.Table,將 generator屬性的值設(shè)置為 SequenceGenerator注釋的 name屬性的值。

    我們以 Animal 實(shí)體類來說明使用數(shù)據(jù)庫表自動(dòng)生成實(shí)體標(biāo)識所需要采取的步驟:我們假設(shè)存在這樣的場景,Animal 實(shí)體的標(biāo)識由應(yīng)用程序中自定義的數(shù)據(jù)庫表 MY_KEYS自動(dòng)生成,MY_KEYS表中有兩列,一列是 KEYID,它保存實(shí)體標(biāo)識的特征值,一列是 KEYVALUE,它保存實(shí)體當(dāng)前的最大編號,除此之外,我們還決定使用 ANIMALID作為 Animal 實(shí)體標(biāo)識的特征字符串。

    首先,在數(shù)據(jù)庫中使用下面的 SQL 語句創(chuàng)建名為 MY_KEYS的數(shù)據(jù)庫表。在 OpenJPA 容器中,如果我們沒有創(chuàng)建 MY_KEYS表,OpenJPA 容器將幫我們自動(dòng)生成對應(yīng)的表結(jié)構(gòu)。


    清單 9. 創(chuàng)建數(shù)據(jù)庫表 MY_KEYS
                CREATE TABLE MY_KEYS (
                KEYID VARCHAR(255) NOT NULL,
                KEYVALUE BIGINT,
                PRIMARY KEY (KEYID)
                )
                

    在數(shù)據(jù)庫部分創(chuàng)建合適的數(shù)據(jù)庫表后,在實(shí)體 Animal 的定義中,我們需要將 id字段 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.TABLE,設(shè)置它的 generator屬性的值為 TableGenerator。我們還需要為 id字段提供另外一個(gè)注釋 TableGenerator,設(shè)置它的 name屬性為 TableGenerator,設(shè)置它的 table屬性為 MYKEYSpkColumnName屬性為 KEYID、valueColumnName屬性為 KEYVALUEANIMALID屬性為 ANIMALID。Animal 實(shí)體類修改后的代碼片段如下。


    清單 10. 標(biāo)識由數(shù)據(jù)庫表生成的 Animal 實(shí)體類
                1. import javax.persistence.Entity;
                2. import javax.persistence.GeneratedValue;
                3. import javax.persistence.GenerationType;
                4. import javax.persistence.Id;
                5.
                6. @Entity
                7. public class Animal {
                8.     @Id
                9.     @GeneratedValue(strategy = GenerationType.TABLE,
                generator = " TableGenerator ")
                10.    @TableGenerator(name = " TableGenerator", table = "MY_KEYS",
                pkColumnName = "KEYID", valueColumnName = "KEYVALUE",
                pkColumnValue = "ANIMALID")
                11.    private long id;
                12.    private String name;
                13.
                14.    …
                15.
                16. }
                


    調(diào)用代碼

    上面的章節(jié)中我們學(xué)習(xí)了分別使用四種方式來自動(dòng)生成實(shí)體的標(biāo)識,由于這四種情況下,Animal 實(shí)體的標(biāo)識都由 OpenJPA 和數(shù)據(jù)庫協(xié)作后自動(dòng)生成,對于開發(fā)者而言,這個(gè)過程是透明的,因此我們可以使用相同的方式來創(chuàng)建這些實(shí)體:創(chuàng)建新的 Animal 實(shí)例的時(shí)候不再需要為主鍵字段提供屬性值,只需要設(shè)置 Animal 實(shí)例的非標(biāo)識字段 name的值即可。下面的代碼演示了 Animal 實(shí)例的持久化代碼,請注意代碼中并沒有調(diào)用 Animal 實(shí)例的 setId 方法。


    清單 11. Animal 實(shí)例的持久化代碼
                1. 	 EntityManagerFactory factory = Persistence.
                2. 	         createEntityManagerFactory(
                3. 	         "jpa-unit", System.getProperties());
                4. 		 EntityManager em = factory.createEntityManager();
                5. 		 em.getTransaction().begin();
                6.
                7. 		 Animal animal = new Animal();
                8. 		 // 此處不需要調(diào)用 animal 的 setId 方法
                9. 		 animal.setName("ba guai!");
                10. 	 em.persist(animal);
                11.
                12. 	 em.getTransaction().commit();
                13. 	 em.close();
                14. 	 em2.close();
                15. 	 factory.close();
                


    總結(jié)

    本文介紹了開發(fā)者使用 OpenJPA 實(shí)現(xiàn)實(shí)體標(biāo)識自動(dòng)生成時(shí)可選擇使用的注釋,并且結(jié)合簡單的例子,分別介紹了 OpenJPA 中實(shí)現(xiàn)容器管理的實(shí)體標(biāo)識自動(dòng)生成、結(jié)合數(shù)據(jù)庫自增長字段、序列號、數(shù)據(jù)庫表等特性實(shí)現(xiàn)實(shí)體標(biāo)識自動(dòng)生成時(shí)注釋的具體用法和操作步驟。


    http://www.ibm.com/developerworks/cn/java/j-lo-openjpa5/


    posted on 2011-05-03 23:06 Alpha 閱讀(13006) 評論(0)  編輯  收藏 所屬分類: MySQL NoSQL
    主站蜘蛛池模板: 国产成人AV免费观看| 久久亚洲AV成人无码软件| 羞羞网站免费观看| 夜夜嘿视频免费看| 亚洲av无码一区二区三区在线播放| 在线看片人成视频免费无遮挡| 亚洲欧洲精品成人久久曰| 在线观看免费成人| 国产精品亚洲一区二区无码| 亚洲日本va午夜中文字幕久久| 精精国产www视频在线观看免费| 亚洲精品国产美女久久久| 女人体1963午夜免费视频| 久久av无码专区亚洲av桃花岛| 精品国产污污免费网站aⅴ | 日本精品久久久久久久久免费| 四虎影视永久免费观看地址| caoporn成人免费公开| 亚洲av永久无码精品国产精品| 国产精品免费精品自在线观看| 亚洲日韩看片无码电影| 免费在线一级毛片| 国产va在线观看免费| tom影院亚洲国产一区二区| 国产又黄又爽又刺激的免费网址| 永久免费精品影视网站| 亚洲人成电影福利在线播放| 最近免费中文字幕大全视频| 三年片在线观看免费观看大全中国| 久久九九亚洲精品| 妞干网在线免费观看| 亚欧国产一级在线免费| 亚洲成年人电影网站| 亚洲av日韩av欧v在线天堂| 蜜桃视频在线观看免费视频网站WWW| 2020亚洲男人天堂精品| 国产亚洲精品资在线| 无限动漫网在线观看免费| xxxxx做受大片在线观看免费| 亚洲视频网站在线观看| 亚洲成片观看四虎永久|