將當前主鍵的值單獨保存到一個數據庫的表中,主鍵的值每次都是從指定的表中查詢來獲得,這種生成主鍵的方式也是很常用的。這種方法生成主鍵的策略可以適用於任何的數據庫,不必擔心不同數據庫不兼容造成的問題。
使用以下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);
現在有另外兩個表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);
添加新數據後表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小節。
用一個簡單示意圖表示持久化主鍵表和表生成策略,如圖所示。