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

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

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

    隨筆-179  評(píng)論-666  文章-29  trackbacks-0

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

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

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

    可選擇的注釋

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

    @javax.persistence.GeneratedValue

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

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

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

    • strategy

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

      • GeneratorType.AUTO

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

      • GenerationType.IDENTITY

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

      • GenerationType.SEQUENCE

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

      • GenerationType.TABLE

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

    • String generator

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

    @javax.persistence.SequenceGenerator

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


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

    @javax.persistence.TableGenerator

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


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

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

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

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

    容器自動(dòng)生成

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

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

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

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

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


    清單 1. 標(biāo)識(shí)由容器自動(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 語(yǔ)句 SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID=0,從默認(rèn)保存實(shí)體標(biāo)識(shí)的 OPENJPA_SEQUENCE_TABLE表中獲取實(shí)體的標(biāo)識(shí),如果不存在 ID為 0 的記錄,OpenJPA 框架自動(dòng)將實(shí)體的標(biāo)識(shí)設(shè)置為 1。

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

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

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

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

    uuid-string

    要使用 uuid-string 機(jī)制自動(dòng)生成實(shí)體標(biāo)識(shí),我們需要將實(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)識(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, 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í),我們必須將實(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)識(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, generator = "uuid-hex")
                10. 		 private String id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    自增長(zhǎng)字段

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

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

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

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


    清單 4. 將 ID 字段設(shè)置為自動(dòng)增長(zhǎng)類型的 SQL 語(yǔ)句
                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ù)庫(kù)部分將表的主鍵字段設(shè)置為自動(dòng)增長(zhǎng)字段后,在實(shí)體 Animal的定義中,我們需要將 id字段 GeneratedValue注釋的 stragety屬性的值設(shè)置為 GenerationType.IDENTITY。Animal 實(shí)體類修改后的代碼片段如下。


    清單 5. 標(biāo)識(shí)由自增長(zhǎ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.IDENTITY)
                10. 		 private long id;
                11. 		 private String name;
                12.
                13. 	  …
                14.
                15. 	 }
                

    序列號(hào)(Sequence)

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

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

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

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


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

    然后,在 Oracle 數(shù)據(jù)庫(kù)中,我們使用下面的 SQL 語(yǔ)句創(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ù)庫(kù)部分創(chuàng)建合適的序列號(hào)和相應(yīng)的數(shù)據(jù)庫(kù)表后,在實(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)識(shí)由序列號(hà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ù)庫(kù)表

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

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

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

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


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

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


    清單 10. 標(biāo)識(shí)由數(shù)據(jù)庫(kù)表生成的 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)識(shí),由于這四種情況下,Animal 實(shí)體的標(biāo)識(shí)都由 OpenJPA 和數(shù)據(jù)庫(kù)協(xié)作后自動(dòng)生成,對(duì)于開發(fā)者而言,這個(gè)過程是透明的,因此我們可以使用相同的方式來創(chuàng)建這些實(shí)體:創(chuàng)建新的 Animal 實(shí)例的時(shí)候不再需要為主鍵字段提供屬性值,只需要設(shè)置 Animal 實(shí)例的非標(biāo)識(shí)字段 name的值即可。下面的代碼演示了 Animal 實(shí)例的持久化代碼,請(qǐng)注意代碼中并沒有調(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)識(shí)自動(dòng)生成時(shí)可選擇使用的注釋,并且結(jié)合簡(jiǎn)單的例子,分別介紹了 OpenJPA 中實(shí)現(xiàn)容器管理的實(shí)體標(biāo)識(shí)自動(dòng)生成、結(jié)合數(shù)據(jù)庫(kù)自增長(zhǎng)字段、序列號(hào)、數(shù)據(jù)庫(kù)表等特性實(shí)現(xiàn)實(shí)體標(biāo)識(shí)自動(dòng)生成時(shí)注釋的具體用法和操作步驟。


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


    posted on 2011-05-03 23:06 Alpha 閱讀(12995) 評(píng)論(0)  編輯  收藏 所屬分類: MySQL NoSQL
    主站蜘蛛池模板: 91人成网站色www免费下载| 色婷婷综合缴情综免费观看| 免费无码黄网站在线看| 国产99视频免费精品是看6| 亚洲一本到无码av中文字幕| 国产精品视频免费一区二区| 99亚洲精品高清一二区| 131美女爱做免费毛片| 亚洲网站在线免费观看| 免费观看黄色的网站| 久久综合亚洲色一区二区三区| 日本免费人成视频在线观看| 亚洲天天做日日做天天欢毛片| 亚洲精品免费观看| 久久久久久久亚洲Av无码| 91成人免费观看网站| 国产成人精品亚洲日本在线 | 98精品全国免费观看视频| 亚洲不卡av不卡一区二区| 另类免费视频一区二区在线观看 | 久久免费国产精品一区二区| 亚洲国产成人精品不卡青青草原| 久久aa毛片免费播放嗯啊| 亚洲国产日韩在线成人蜜芽| 成年女人毛片免费播放人| 色婷婷精品免费视频| 亚洲乱码一区二区三区在线观看 | 国产亚洲一区二区在线观看| 日韩免费观看一区| 久久精品国产亚洲av麻豆蜜芽| 国产成人免费福利网站| 91视频免费观看高清观看完整| 亚洲视频中文字幕在线| 成年女人毛片免费观看97| 72pao国产成视频永久免费| 亚洲精品综合久久中文字幕| 成年午夜视频免费观看视频| 春意影院午夜爽爽爽免费| 亚洲国产精品久久久久久| 在线成人a毛片免费播放 | 亚洲免费视频网站|