JPA annotation 筆記
@Id 顧名思義,就不多說(shuō)了。
@GeneratedValue:主鍵的產(chǎn)生策略,通過(guò)strategy屬性指定。
默認(rèn)情況下,JPA自動(dòng)選擇一個(gè)最適合底層數(shù)據(jù)庫(kù)的主鍵生成策略,如SqlServer對(duì)應(yīng)identity,MySql對(duì)應(yīng)auto increment。
在javax.persistence.GenerationType中定義了以下幾種可供選擇的策略:
1) IDENTITY:表自增鍵字段,Oracle不支持這種方式;
2) AUTO: JPA自動(dòng)選擇合適的策略,是默認(rèn)選項(xiàng);
3) SEQUENCE:通過(guò)序列產(chǎn)生主鍵,通過(guò)@SequenceGenerator注解指定序列名,MySql不支持這種方式;
4) TABLE:通過(guò)表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫(kù)移植。
這里我重點(diǎn)來(lái)說(shuō)下GenerationType.TABLE的情況。
把庫(kù)表的主鍵auto_increment去掉
CREATE TABLE `t_creditcard` (
`id` int(11) NOT NULL,
`cardName` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `id_gen` (
`gen_name` varchar(80) NOT NULL default '',
`gen_val` int(11) default NULL,
PRIMARY KEY (`gen_name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
@Entity
@Table(name="t_creditcard")
public class CreditCard{
@TableGenerator(name = "CardPkGen",
table = "ID_GEN",
pkColumnName = "GEN_NAME",
pkColumnValue = "Card_Gen",
valueColumnName = "GEN_VAL",
allocationSize = 1
)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")
private Long id;
@GeneratedValue:定義主鍵生成策略,這里因?yàn)槭褂玫氖荰ableGenerator,所以,主鍵的生成策略為GenerationType.TABLE,生成主鍵策略的名稱(chēng)則為前面定義的"CardPkGen”。
@TableGenerator各屬性含義如下:
name:表示該表主鍵生成策略的名稱(chēng),這個(gè)名字可以自定義,它被引用在@GeneratedValue中設(shè)置的"generator"值中
table:表示表生成策略所持久化的表名,說(shuō)簡(jiǎn)單點(diǎn)就是一個(gè)管理其它表主鍵的表,本例中,這個(gè)表名為ID_GEN
pkColumnName:表生成器中的列名,用來(lái)存放其它表的主鍵鍵名,一般來(lái)說(shuō)一個(gè)主鍵鍵名對(duì)應(yīng)一張其他表要獲取主鍵值對(duì)應(yīng)的key。這個(gè)值要與數(shù)據(jù)庫(kù)的列對(duì)應(yīng),比如GEN_NAME對(duì)應(yīng)id_gen中的主鍵名稱(chēng)
pkColumnValue:該實(shí)體所要訪問(wèn)對(duì)應(yīng)主鍵生成表的主鍵的key值
valueColumnName:表生成器所要對(duì)應(yīng)pkColumnName主鍵的下一個(gè)值,這個(gè)值也要和表生成器中的列名對(duì)應(yīng)
allocationSize:表示每次主鍵值增加的大小,例如設(shè)置成1,則表示每次創(chuàng)建新記錄后自動(dòng)加1,默認(rèn)為50
按照以上結(jié)構(gòu),如果我們執(zhí)行:
CreditCard cc = new CreditCard();
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 2
表t_creditcard內(nèi)的數(shù)據(jù)為
ID CARDNAME
1 測(cè)試卡
再執(zhí)行一次程序
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 3
表t_creditcard內(nèi)的數(shù)據(jù)為
ID CARDNAME
1 測(cè)試卡
2 測(cè)試卡
把實(shí)體類(lèi)的annation改寫(xiě)為:
@Entity
@Table(name="t_creditcard")
public class CreditCard{
@TableGenerator(name = "CardPkGen",
table = "ID_GEN",
pkColumnName = "GEN_NAME",
pkColumnValue = "Card_Gen2",
valueColumnName = "GEN_VAL",
allocationSize = 1
)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")
private Long id;
注意看,pkColumnValue已經(jīng)被改為Card_Gen2。
執(zhí)行程序,插入數(shù)據(jù)失敗,拋出t_creditcard表主鍵重復(fù)的異常,因?yàn)檫@次去名為Card_Gen2的這個(gè)主鍵生成器去拿來(lái)的id為1,t_creditcard表之前已經(jīng)插入過(guò)一條主鍵為1的數(shù)據(jù)了。
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 3
Card_Gen2 2
表t_creditcard內(nèi)的數(shù)據(jù)還是為
ID CARDNAME
1 測(cè)試卡
2 測(cè)試卡
結(jié)論:在有些應(yīng)用中,我們可以適用@TableGenerator來(lái)統(tǒng)一管理我們數(shù)據(jù)庫(kù)中的各個(gè)表的主鍵生成,如果我們的應(yīng)用中有10個(gè)實(shí)體需要使用自動(dòng)生成的主鍵,只需在每個(gè)實(shí)體中使用@TableGenerator并給出不同的pkColumnValue值就可以了。
@Id還有一些另類(lèi)的用法:
1.使用系統(tǒng)毫秒數(shù)作為主鍵
@Id
private Long id = System.currentTimeMillis();
CreditCard cc = new CreditCard();
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
2.使用UUID作為主鍵
@Id
private String id;;
CreditCard cc = new CreditCard();
cc.setId(UUID.randomUUID().toString());
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
別忘了修改庫(kù)表中主鍵字段的大小和對(duì)應(yīng)的類(lèi)型.
@GeneratedValue:主鍵的產(chǎn)生策略,通過(guò)strategy屬性指定。
默認(rèn)情況下,JPA自動(dòng)選擇一個(gè)最適合底層數(shù)據(jù)庫(kù)的主鍵生成策略,如SqlServer對(duì)應(yīng)identity,MySql對(duì)應(yīng)auto increment。
在javax.persistence.GenerationType中定義了以下幾種可供選擇的策略:
1) IDENTITY:表自增鍵字段,Oracle不支持這種方式;
2) AUTO: JPA自動(dòng)選擇合適的策略,是默認(rèn)選項(xiàng);
3) SEQUENCE:通過(guò)序列產(chǎn)生主鍵,通過(guò)@SequenceGenerator注解指定序列名,MySql不支持這種方式;
4) TABLE:通過(guò)表產(chǎn)生主鍵,框架借由表模擬序列產(chǎn)生主鍵,使用該策略可以使應(yīng)用更易于數(shù)據(jù)庫(kù)移植。
這里我重點(diǎn)來(lái)說(shuō)下GenerationType.TABLE的情況。
把庫(kù)表的主鍵auto_increment去掉
CREATE TABLE `t_creditcard` (
`id` int(11) NOT NULL,
`cardName` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `id_gen` (
`gen_name` varchar(80) NOT NULL default '',
`gen_val` int(11) default NULL,
PRIMARY KEY (`gen_name`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
@Entity
@Table(name="t_creditcard")
public class CreditCard{
@TableGenerator(name = "CardPkGen",
table = "ID_GEN",
pkColumnName = "GEN_NAME",
pkColumnValue = "Card_Gen",
valueColumnName = "GEN_VAL",
allocationSize = 1
)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")
private Long id;
@GeneratedValue:定義主鍵生成策略,這里因?yàn)槭褂玫氖荰ableGenerator,所以,主鍵的生成策略為GenerationType.TABLE,生成主鍵策略的名稱(chēng)則為前面定義的"CardPkGen”。
@TableGenerator各屬性含義如下:
name:表示該表主鍵生成策略的名稱(chēng),這個(gè)名字可以自定義,它被引用在@GeneratedValue中設(shè)置的"generator"值中
table:表示表生成策略所持久化的表名,說(shuō)簡(jiǎn)單點(diǎn)就是一個(gè)管理其它表主鍵的表,本例中,這個(gè)表名為ID_GEN
pkColumnName:表生成器中的列名,用來(lái)存放其它表的主鍵鍵名,一般來(lái)說(shuō)一個(gè)主鍵鍵名對(duì)應(yīng)一張其他表要獲取主鍵值對(duì)應(yīng)的key。這個(gè)值要與數(shù)據(jù)庫(kù)的列對(duì)應(yīng),比如GEN_NAME對(duì)應(yīng)id_gen中的主鍵名稱(chēng)
pkColumnValue:該實(shí)體所要訪問(wèn)對(duì)應(yīng)主鍵生成表的主鍵的key值
valueColumnName:表生成器所要對(duì)應(yīng)pkColumnName主鍵的下一個(gè)值,這個(gè)值也要和表生成器中的列名對(duì)應(yīng)
allocationSize:表示每次主鍵值增加的大小,例如設(shè)置成1,則表示每次創(chuàng)建新記錄后自動(dòng)加1,默認(rèn)為50
按照以上結(jié)構(gòu),如果我們執(zhí)行:
CreditCard cc = new CreditCard();
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 2
表t_creditcard內(nèi)的數(shù)據(jù)為
ID CARDNAME
1 測(cè)試卡
再執(zhí)行一次程序
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 3
表t_creditcard內(nèi)的數(shù)據(jù)為
ID CARDNAME
1 測(cè)試卡
2 測(cè)試卡
把實(shí)體類(lèi)的annation改寫(xiě)為:
@Entity
@Table(name="t_creditcard")
public class CreditCard{
@TableGenerator(name = "CardPkGen",
table = "ID_GEN",
pkColumnName = "GEN_NAME",
pkColumnValue = "Card_Gen2",
valueColumnName = "GEN_VAL",
allocationSize = 1
)
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="CardPkGen")
private Long id;
注意看,pkColumnValue已經(jīng)被改為Card_Gen2。
執(zhí)行程序,插入數(shù)據(jù)失敗,拋出t_creditcard表主鍵重復(fù)的異常,因?yàn)檫@次去名為Card_Gen2的這個(gè)主鍵生成器去拿來(lái)的id為1,t_creditcard表之前已經(jīng)插入過(guò)一條主鍵為1的數(shù)據(jù)了。
表id_gen內(nèi)的數(shù)據(jù)為
GEN_NAME GEN_VALUE
Card_Gen 3
Card_Gen2 2
表t_creditcard內(nèi)的數(shù)據(jù)還是為
ID CARDNAME
1 測(cè)試卡
2 測(cè)試卡
結(jié)論:在有些應(yīng)用中,我們可以適用@TableGenerator來(lái)統(tǒng)一管理我們數(shù)據(jù)庫(kù)中的各個(gè)表的主鍵生成,如果我們的應(yīng)用中有10個(gè)實(shí)體需要使用自動(dòng)生成的主鍵,只需在每個(gè)實(shí)體中使用@TableGenerator并給出不同的pkColumnValue值就可以了。
@Id還有一些另類(lèi)的用法:
1.使用系統(tǒng)毫秒數(shù)作為主鍵
@Id
private Long id = System.currentTimeMillis();
CreditCard cc = new CreditCard();
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
2.使用UUID作為主鍵
@Id
private String id;;
CreditCard cc = new CreditCard();
cc.setId(UUID.randomUUID().toString());
cc.setCardName("測(cè)試卡");
cc = ccDao.persist(cc);
別忘了修改庫(kù)表中主鍵字段的大小和對(duì)應(yīng)的類(lèi)型.
posted on 2009-02-22 22:08 草原上的駱駝 閱讀(1664) 評(píng)論(0) 編輯 收藏 所屬分類(lèi): JAVA框架