jpa中用table來生成主鍵
將當前主鍵的值單獨保存到一個數據庫的表中,主鍵的值每次都是從指定的表中查詢來獲得,這種生成主鍵的方式也是很常用的。這種方法生成主鍵的策略可以適用于任何的數據庫,不必擔心不同數據庫不兼容造成的問題。
使用以下SQL腳本創建一個表“tb_generator”,并插入兩條數據,SQL腳本如下所示。
CREATE TABLE? tb_generator (
? id int(20) unsigned NOT NULL auto_increment,
? gen_name varchar(255) NOT NULL,
? gen_value int(20) NOT NULL,
? PRIMARY KEY? (id)
)
?
INSERT INTO tb_generator ( gen_name ,gen_value ) VALUES ( 'CUSTOMER_PK',1);
INSERT INTO tb_generator ( gen_name ,gen_value ) VALUES ( 'CONTACT_PK',100);
執行SQL語句后,表中的數據如圖5.1所示。
圖5.1? 自動生成主鍵表tb_generator
現在有另外兩個表customer和contact,它們每次新建記錄時生成主鍵的值分別“CUSTOMER_PK”所對應的value值加1,“CONTACT_PK”所對應的value值加1。
下面就來具體看一下如何來配置主鍵的生成策略,以配置“customer”表為例,步驟如下。
(1)在Entity標記主鍵的位置,指定主鍵生成策略為“GenerationType.TABLE”,具體設置如下。
@Entity
@Table(name = "customer")
public final class CustomerEO implements java.io.Serializable {
?
???????? private Integer id;
?
???????? @Id
???????? @GeneratedValue(strategy = GenerationType.TABLE)
???????? public Integer getId() {
?????????????????? return this.id;
???????? }
?
???????? public void setId(Integer id) {
?????????????????? this.id = id;
???????? }
}
(2)指定生成主鍵策略的名稱,例如這里命名為“customer_gen”。
???????? @Id
???????? @GeneratedValue(strategy = GenerationType.TABLE,generator="customer_gen")
???????? public Integer getId() {
?????????????????? return this.id;
???????? }
(3)使用@ TableGenerator標記定義表生成策略的具體設置,代碼如下所示。
???????? @Id
???????? @GeneratedValue(strategy = GenerationType.TABLE,generator="customer_gen")
???????? @TableGenerator(name = "customer_gen",
??????????????????????????? table="tb_generator",
??????????????????????????? pkColumnName="gen_name",
??????????????????????????? valueColumnName="gen_value",
??????????????????????????? pkColumnValue="CUSTOMER_PK",
??????????????????????????? allocationSize=1
???????? )
???????? public Integer getId() {
?????????????????? return this.id;
???????? }
這樣,當通過以下代碼創建新的實體后,表tb_generator中“CUSTOMER_PK”的value的值將自動加1,如圖5.2所示。
???????????? CustomerEO customer = new CustomerEO();
???????????? customer.setName("Janet");
???????????? customer.setShortName("Jane");
???????????? entityManager.persist(customer);
圖5.2? 添加新數據后表tb_generator
(4)@TableGenerator標記用于設置主鍵使用數據表生成主鍵的策略,它的定義如下所示。
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface TableGenerator {
String name();
String table() default "";
String catalog() default "";
String schema() default "";
String pkColumnName() default "";
String valueColumnName() default "";
String pkColumnValue() default "";
int initialValue() default 0;
int allocationSize() default 50;
UniqueConstraint[] uniqueConstraints() default {};
}
在使用此@ TableGenerator標記時,需要注意以下幾個問題。
l???????? 該標記可以在類名、方法名、和屬性名前。并且一旦在實體中標記,它不僅可以在本實體中使用,在其他的實體中也可以引用。它的作用范圍是整個persist unit配置的實體類中。
例如以上的定義也可以寫成:
@Entity
@Table(name = "customer")
@TableGenerator(name = "customer_gen",
?????????????????? table="tb_generator",
?????????????????? pkColumnName="gen_name",
?????????????????? valueColumnName="gen_value",
?????????????????? pkColumnValue="CUSTOMER_PK",
?????????????????? allocationSize=1
)
public class CustomerEO implements java.io.Serializable {
???????? ……
}
或者將其標注在ContactEO中,也是可以的。但建議標注在所作用的實體中,這樣有助于方便查看。
l???????? name屬性表示該表主鍵生成策略的名稱,它被引用在@GeneratedValue中設置的“generator”值中。
l???????? table屬性表示表生成策略所持久化的表名,例如,這里表使用的是數據庫中的“tb_generator”。
l???????? catalog屬性和schema具體指定表所在的目錄名或是數據庫名。
l???????? pkColumnName屬性的值表示在持久化表中,該主鍵生成策略所對應鍵值的名稱。例如在“tb_generator”中將“gen_name”作為主鍵的鍵值
l???????? valueColumnName屬性的值表示在持久化表中,該主鍵當前所生成的值,它的值將會隨著每次創建累加。例如,在“tb_generator”中將“gen_value”作為主鍵的值
l???????? pkColumnValue屬性的值表示在持久化表中,該生成策略所對應的主鍵。例如在“tb_generator”表中,將“gen_name”的值為“CUSTOMER_PK”。
l???????? initialValue表示主鍵初識值,默認為0。
l???????? allocationSize表示每次主鍵值增加的大小,例如設置成1,則表示每次創建新記錄后自動加1,默認為50。
l???????? UniqueConstraint與@Table標記中的用法類似,請讀者參閱5.2.1小節。
用一個簡單示意圖表示持久化主鍵表和表生成策略,如圖所示。
?
二.EJB3.0里的實體bean主鍵產生類型有一種是 GenerationType.TABLE,數據表如下:
?
?
?
?
?
?
?
里面有的一條示例數據:
gen_key | gen_value |
VENDOR_PART_ID | 5 |
?
?
部分代碼如下:
- @SuppressWarnings ( "serial" ) ??
- @Entity ??
- @Table (name= "vendorpart" ) ??
- public ? class ?VendorPart? implements ?Serializable?{ ??
- ??
- ???? private ?Long?vendorpartNumber; ??
- ???? private ?String?myDescription; ??
- ???? private ? double ?price; ??
- ???? ??
- ???? private ?Vendor?vendor; ??
- ???? private ?Part?part; ??
- ??
- ???? @TableGenerator ( ??
- ????????????name= "vendorPartGen" ,? //?命名表產生器 ??
- ????????????table= "sequencegenerator" ,? //?表產生器產生主鍵的表 ??
- ????????????pkColumnName= "gen_key" ,? //?主鍵表中主鍵列名 ??
- ????????????pkColumnValue= "VENDOR_PART_ID" ,? //?主鍵表中某個主鍵列 ??
- ????????????allocationSize= 10 , ??
- ????????????valueColumnName= "gen_value" ? //?主鍵表中主鍵值的列名 ??
- ????) ??
- ???? @Id ??
- ???? @Column (name= "vendorpartnumber" ) ??
- ???? @GeneratedValue (strategy=GenerationType.TABLE,generator= "vendorPartGen" )???? //?產生器名字 ??
- ???? public ?Long?getVendorpartNumber()?{ ??
- ???????? return ?vendorpartNumber; ??
- ????} ??
- ??
- ???? public ? void ?setVendorpartNumber(Long?vendorpartNumber)?{ ??
- ???????? this .vendorpartNumber?=?vendorpartNumber; ??
- ????} ??
- ??
- //?。。。。 ??
- ??
- }??
?
posted on 2009-06-25 17:59 tobyxiong 閱讀(1192) 評論(0) 編輯 收藏 所屬分類: java