1才避、native-重點(diǎn)
native由hibernate根據(jù)使用的數(shù)據(jù)庫(kù)自行判斷采用identity漓糙、hilo吏祸、sequence其中一種作為主鍵生成方式竞端,靈活性很強(qiáng)。如果能支持identity則使用identity锻霎,如果支持sequence則使用sequence著角。
數(shù)據(jù)庫(kù)ID必須設(shè)置為自動(dòng)增長(zhǎng)列,不能手動(dòng)賦值(數(shù)據(jù)類型必須是int類型)旋恼;當(dāng)數(shù)據(jù)庫(kù)為int類型時(shí)吏口,最好使用主鍵類型為native(能夠跨數(shù)據(jù)庫(kù))
<id name="id" column="id">
<!--MySQL使用identity(id主鍵需要設(shè)置自增),Oracle使用sequence(hibernate默認(rèn)查找hibernate_sequence序列,如果沒有需要自己創(chuàng)建)-->
<generator class="native" />
</id>
例如MySQL使用identity,Oracle使用sequence
MySQL使用identity: id主鍵必須自增類型
id INT UNSIGNED AUTO_INCREMENT
注意:如果Hibernate自動(dòng)選擇sequence或者h(yuǎn)ilo产徊,則所有的表的主鍵都會(huì)從Hibernate默認(rèn)的sequence或hilo表中取昂勒。并且,有的數(shù)據(jù)庫(kù)對(duì)于默認(rèn)情況主鍵生成測(cè)試的支持舟铜,效率并不是很高戈盈。
使用sequence或hilo時(shí),可以加入?yún)?shù)谆刨,指定sequence名稱或hi值表名稱等塘娶,如
<id name="id" column="id" type="int">
<!--根據(jù)數(shù)據(jù)庫(kù)自動(dòng)選擇identity、hilo痴荐、sequence其中一種血柳,例如MySQL使用identity官册,Oracle使用sequence(默認(rèn)序列查找hibernate_sequence序列)生兆,使用自定義序列時(shí)需加入?yún)?shù)sequence_name-->
<generator class="native">
<!--SEQ_MY_HIBERNATE 是自定義創(chuàng)建的序列-->
<param name="sequence_name">SEQ_MY_HIBERNATE</param>
</generator>
</id>
oracle創(chuàng)建序列
--oracle創(chuàng)建序列語(yǔ)句
--創(chuàng)建序列 SEQ_MY_HIBERNATE
create sequence SEQ_MY_HIBERNATE
minvalue 1
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
--創(chuàng)建序列 hibernate_sequence
create sequence hibernate_sequence
minvalue 1
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
特點(diǎn):根據(jù)數(shù)據(jù)庫(kù)自動(dòng)選擇,項(xiàng)目中如果用到多個(gè)數(shù)據(jù)庫(kù)時(shí)膝宁,可以使用這種方式鸦难,使用時(shí)需要設(shè)置表的自增字段或建立序列,建立表等员淫。
2合蔽、increment-重點(diǎn)
由Hibernate從數(shù)據(jù)庫(kù)中取出主鍵的最大值(每個(gè)session只取1次),以該值為基礎(chǔ)介返,每次增量為1拴事,在內(nèi)存中生成主鍵,不依賴于底層的數(shù)據(jù)庫(kù)圣蝎,因此可以跨數(shù)據(jù)庫(kù)刃宵。
數(shù)據(jù)庫(kù)ID可不設(shè)置為自動(dòng)增長(zhǎng)列,不能手動(dòng)賦值(數(shù)據(jù)類型必須為int類型)徘公;
<id name="id" column="id" type="int">
<!--在內(nèi)存中生成主鍵牲证,不依賴于底層的數(shù)據(jù)庫(kù),因此可以跨數(shù)據(jù)庫(kù),首次從數(shù)據(jù)庫(kù)取主鍵最大的值-->
<generator class="increment" />
</id>
Hibernate調(diào)用org.hibernate.id.IncrementGenerator類里面的generate()方法关面,使用 select max(idColumnName) from tableName 語(yǔ)句獲取主鍵最大值坦袍。該方法被聲明成了synchronized,所以在一個(gè)獨(dú)立的Java虛擬機(jī)內(nèi)部是沒有問題的等太,然而捂齐,在多個(gè)JVM同時(shí)并發(fā)訪問數(shù)據(jù)庫(kù)select max時(shí)就可能取出相同的值,再insert就會(huì)發(fā)生Dumplicate entry的錯(cuò)誤缩抡。所以只能有一個(gè)Hibernate應(yīng)用進(jìn)程訪問數(shù)據(jù)庫(kù)奠宜,否則就可能產(chǎn)生主鍵沖突,所以不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫(kù),適合單一進(jìn)程訪問數(shù)據(jù)庫(kù)挎塌,不能用于群集環(huán)境徘六。
官方文檔:只有在沒有其他進(jìn)程往同一張表中插入數(shù)據(jù)時(shí)才能使用,在集群下不要使用榴都。
特點(diǎn):跨數(shù)據(jù)庫(kù)待锈,不適合多進(jìn)程并發(fā)更新數(shù)據(jù)庫(kù),適合單一進(jìn)程訪問數(shù)據(jù)庫(kù)嘴高,不能用于群集環(huán)境竿音。
3、sequence-重點(diǎn)
采用數(shù)據(jù)庫(kù)提供的sequence機(jī)制生成主鍵拴驮,需要數(shù)據(jù)庫(kù)支持sequence春瞬。如oralce、DB套啤、SAP DB宽气、PostgerSQL、McKoi中的sequence潜沦。MySQL這種不支持sequence的數(shù)據(jù)庫(kù)則不行(可以使用identity)萄涯。
采用數(shù)據(jù)庫(kù)提供的sequence機(jī)制生成主鍵。MySql數(shù)據(jù)庫(kù)不支持唆鸡。(數(shù)據(jù)類型必須是int類型)涝影。
<id name="id" column="id" type="int">
<!--使用sequence,hibernate默認(rèn)查找hibernate_sequence序列,如果沒有需要自己創(chuàng)建序列-->
<generator class="sequence">
<!--SEQ_MY_HIBERNATE 是自定義創(chuàng)建的序列争占,指定sequence的名稱-->
<param name="sequence_name">SEQ_MY_HIBERNATE</param>
</generator>
</id>
oracle創(chuàng)建序列
--oracle創(chuàng)建序列語(yǔ)句
--創(chuàng)建序列 SEQ_MY_HIBERNATE
create sequence SEQ_MY_HIBERNATE
minvalue 1
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
--創(chuàng)建序列 hibernate_sequence
create sequence hibernate_sequence
minvalue 1
maxvalue 9999999999999999999999999999
start with 1
increment by 1
cache 20;
Hibernate生成主鍵時(shí)燃逻,查找sequence并賦給主鍵值,主鍵值由數(shù)據(jù)庫(kù)生成臂痕,Hibernate不負(fù)責(zé)維護(hù)伯襟,使用時(shí)必須先創(chuàng)建一個(gè)sequence,如果不指定sequence名稱刻蟹,則使用Hibernate默認(rèn)的sequence逗旁,名稱為hibernate_sequence,前提要在數(shù)據(jù)庫(kù)中創(chuàng)建該sequence舆瘪。
特點(diǎn):只能在支持序列的數(shù)據(jù)庫(kù)中使用片效,如Oracle。
4英古、identity-重點(diǎn)
identity由底層數(shù)據(jù)庫(kù)生成標(biāo)識(shí)符淀衣。identity是由數(shù)據(jù)庫(kù)自己生成的,但這個(gè)主鍵必須設(shè)置為自增長(zhǎng)召调,使用identity的前提條件是底層數(shù)據(jù)庫(kù)支持自動(dòng)增長(zhǎng)字段類型膨桥,如DB2蛮浑、SQL Server、MySQL只嚣、Sybase和HypersonicSQL等沮稚,Oracle這類沒有自增字段的則不支持。
數(shù)據(jù)庫(kù)ID必須設(shè)置為自動(dòng)增長(zhǎng)列册舞,不能手動(dòng)賦值(數(shù)據(jù)類型必須為int類型)蕴掏。
<id name="id" column="id">
<generator class="identity" />
</id>
例:如果使用MySQL數(shù)據(jù)庫(kù),則主鍵字段必須設(shè)置成auto_increment调鲸。
id int(11) primary key auto_increment
特點(diǎn):只能用在支持自動(dòng)增長(zhǎng)的字段數(shù)據(jù)庫(kù)中使用盛杰,如MySQL。
5藐石、uuid-掌握
UUID:Universally Unique Identifier即供,是指在一臺(tái)機(jī)器上生成的數(shù)字,它保證對(duì)在同一時(shí)空中的所有機(jī)器都是唯一的于微。按照開放軟件基金會(huì)(OSF)制定的標(biāo)準(zhǔn)計(jì)算逗嫡,用到了以太網(wǎng)卡地址、納秒級(jí)時(shí)間角雷、芯片ID碼和許多可能的數(shù)字祸穷,標(biāo)準(zhǔn)的UUID格式為:
xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
其中每個(gè) x 是 0-9 或 a-f 范圍內(nèi)的一個(gè)十六進(jìn)制的數(shù)字。
數(shù)據(jù)庫(kù)ID不能設(shè)置為自動(dòng)增長(zhǎng)列勺三,不能手動(dòng)賦值(數(shù)據(jù)類型必須是String類型);生成的是一個(gè)16進(jìn)制的數(shù)字(不能跨數(shù)據(jù)庫(kù))需曾。
<id name="id" column="id">
<generator class="uuid" />
</id>
Hibernate在保存對(duì)象時(shí)吗坚,生成一個(gè)UUID字符串作為主鍵,保證了唯一性呆万,但其并無任何業(yè)務(wù)邏輯意義商源,只能作為主鍵,唯一缺點(diǎn)長(zhǎng)度較大谋减,32位(Hibernate將UUID中間的“-”刪除了)的字符串牡彻,占用存儲(chǔ)空間大,但是有兩個(gè)很重要的優(yōu)點(diǎn)出爹,Hibernate在維護(hù)主鍵時(shí)庄吼,不用去數(shù)據(jù)庫(kù)查詢,從而提高效率严就,而且它是跨數(shù)據(jù)庫(kù)的总寻,以后切換數(shù)據(jù)庫(kù)極其方便。
特點(diǎn):uuid長(zhǎng)度大梢为,占用空間大渐行,跨數(shù)據(jù)庫(kù)轰坊,不用訪問數(shù)據(jù)庫(kù)就生成主鍵值,所以效率高且能保證唯一性祟印,移植非常方便肴沫,推薦使用。
6蕴忆、guid-掌握
GUID:Globally Unique Identifier全球唯一標(biāo)識(shí)符樊零,也稱作 UUID,是一個(gè)128位長(zhǎng)的數(shù)字孽文,用16進(jìn)制表示驻襟。算法的核心思想是結(jié)合機(jī)器的網(wǎng)卡、當(dāng)?shù)貢r(shí)間芋哭、一個(gè)隨即數(shù)來生成GUID沉衣。從理論上講,如果一臺(tái)機(jī)器每秒產(chǎn)生10000000個(gè)GUID减牺,則可以保證(概率意義上)3240年不重復(fù)豌习。
數(shù)據(jù)庫(kù)ID不能設(shè)置為自動(dòng)增長(zhǎng)列,不能手動(dòng)賦值(數(shù)據(jù)類型必須是String類型);
當(dāng)數(shù)據(jù)庫(kù)為String類型時(shí)拔疚,最好使用主鍵類型為guid肥隆。
<id name="id" column="id">
<generator class="guid" />
</id>
Hibernate在維護(hù)主鍵時(shí),先查詢數(shù)據(jù)庫(kù)稚失,獲得一個(gè)uuid字符串栋艳,該字符串就是主鍵值,該值唯一句各,缺點(diǎn)長(zhǎng)度較大吸占,支持?jǐn)?shù)據(jù)庫(kù)有限,優(yōu)點(diǎn)同uuid凿宾,跨數(shù)據(jù)庫(kù)矾屯,但是仍然需要訪問數(shù)據(jù)庫(kù)。
注意:長(zhǎng)度因數(shù)據(jù)庫(kù)不同而不同
MySQL中使用select uuid()語(yǔ)句獲得的為36位(包含標(biāo)準(zhǔn)格式的“-”)
Oracle中初厚,使用select rawtohex(sys_guid()) from dual語(yǔ)句獲得的為32位(不包含“-”)
特點(diǎn):需要數(shù)據(jù)庫(kù)支持查詢uuid件蚕,生成時(shí)需要查詢數(shù)據(jù)庫(kù),效率沒有uuid高产禾,推薦使用uuid排作。
7、assigned-掌握
主鍵由外部程序負(fù)責(zé)生成下愈,在 save() 之前必須指定一個(gè)纽绍。Hibernate不負(fù)責(zé)維護(hù)主鍵生成。與Hibernate和底層數(shù)據(jù)庫(kù)都無關(guān)势似,可以跨數(shù)據(jù)庫(kù)拌夏。在存儲(chǔ)對(duì)象前僧著,必須要使用主鍵的setter方法給主鍵賦值,至于這個(gè)值怎么生成障簿,完全由自己決定盹愚,這種方法應(yīng)該盡量避免。
數(shù)據(jù)庫(kù)ID設(shè)為自動(dòng)增長(zhǎng)列時(shí)站故,在存儲(chǔ)對(duì)象前皆怕,主鍵可手動(dòng)賦值,也可不手動(dòng)賦值西篓; 不賦值執(zhí)行數(shù)據(jù)庫(kù)自動(dòng)增長(zhǎng)愈腾,賦值執(zhí)行賦予的值(數(shù)據(jù)類型為int)。
<id name="id" column="id">
<generator class="assigned" />
</id>
特點(diǎn):可以跨數(shù)據(jù)庫(kù)岂津,人為控制主鍵生成虱黄,應(yīng)盡量避免。
8吮成、hilo-掌握
hilo(高低位方式high low)是hibernate中最常用的一種生成方式橱乱,需要一張額外的表保存hi的值。保存hi值的表至少有一條記錄(只與第一條記錄有關(guān))粱甫,否則會(huì)出現(xiàn)錯(cuò)誤泳叠。可以跨數(shù)據(jù)庫(kù)。
<id name="id" column="id">
<generator class="hilo">
<!--指定保存hi值的表名-->
<param name="table">hibernate_hilo</param>
<!--指定保存hi值的列名-->
<param name="column">next_hi</param>
<!--指定低位的最大值-->
<param name="max_lo">100</param>
</generator>
</id>
也可以省略table和column配置茶宵,其默認(rèn)的表為hibernate_unique_key危纫,列為next_hi
<id name="id" column="id">
<generator class="hilo">
<param name="max_lo">100</param>
</generator>
</id>
hilo生成器生成主鍵的過程(以hibernate_hilo表,next_hi列為例):
獲得hi值:讀取并記錄數(shù)據(jù)庫(kù)的hibernate_hilo表中next_hi字段的值节预,數(shù)據(jù)庫(kù)中此字段值加1保存叶摄。
獲得lo值:從0到max_lo循環(huán)取值,差值為1安拟,當(dāng)值為max_lo值時(shí),重新獲取hi值宵喂,然后lo值繼續(xù)從0到max_lo循環(huán)糠赦。
根據(jù)公式 hi * (max_lo + 1) 計(jì)算生成主鍵值。
注意:當(dāng)hi值是0的時(shí)候锅棕,那么第一個(gè)值不是0*(max_lo+1)+0=0拙泽,而是lo跳過0從1開始,直接是1裸燎、2顾瞻、3……
那max_lo配置多大合適呢?
這要根據(jù)具體情況而定德绿,如果系統(tǒng)一般不重啟荷荤,而且需要用此表建立大量的主鍵退渗,可以吧max_lo配置大一點(diǎn),這樣可以減少讀取數(shù)據(jù)表的次數(shù)蕴纳,提高效率会油;反之,如果服務(wù)器經(jīng)常重啟古毛,可以吧max_lo配置小一點(diǎn)翻翩,可以避免每次重啟主鍵之間的間隔太大,造成主鍵值主鍵不連貫稻薇。
特點(diǎn):跨數(shù)據(jù)庫(kù)嫂冻,hilo算法生成的標(biāo)志只能在一個(gè)數(shù)據(jù)庫(kù)中保證唯一。
9塞椎、seqhilo-掌握
與hilo類似桨仿,通過hi/lo算法實(shí)現(xiàn)的主鍵生成機(jī)制,只是將hilo中的數(shù)據(jù)表?yè)Q成了序列sequence忱屑,需要數(shù)據(jù)庫(kù)中先創(chuàng)建sequence蹬敲,適用于支持sequence的數(shù)據(jù)庫(kù),如Oracle莺戒。
<id name="id" column="id">
<generator class="seqhilo">
<param name="sequence">hibernate_seq</param>
<param name="max_lo">100</param>
</generator>
</id>
特點(diǎn):與hilo類似伴嗡,只能在支持序列的數(shù)據(jù)庫(kù)中使用。
10从铲、foreign
使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的主鍵作為該對(duì)象主鍵瘪校。主要用于一對(duì)一關(guān)系中。
<id name="id" column="id">
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<one-to-one name="user" class="domain.User" constrained="true" />
該例使用domain.User的主鍵作為本類映射的主鍵名段。
特點(diǎn):很少使用阱扬,大多用在一對(duì)一關(guān)系中。
11伸辟、select
使用觸發(fā)器生成主鍵麻惶,主要用于早期的數(shù)據(jù)庫(kù)主鍵生成機(jī)制,能用到的地方非常少
12信夫、自定義主鍵生成器
創(chuàng)建主鍵生成器類窃蹋,實(shí)現(xiàn) org.hibernate.id.IdentifierGenerator 接口。
示例1:讀取數(shù)據(jù)庫(kù)信息來實(shí)現(xiàn)自定義主鍵生成器(缺點(diǎn):查詢了數(shù)據(jù)庫(kù)表中的所有數(shù)據(jù)静稻,讀取速度慢):
public class MyGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session2 = sessionFactory.openSession();
Transaction transaction = session2.beginTransaction();
// 得到數(shù)據(jù)庫(kù)集合
List<Userinfo> lu = session2.createCriteria(Userinfo.class).list();
String str = "";
if (lu.size() > 0) {
for (int i = 0; i < lu.size(); i++) {
str = "Chain_0" + (i + 2);
}
} else {
str = "Chain_01";
}
transaction.commit();
session2.close();
sessionFactory.close();
return str;
}
}
示例2:讀取數(shù)據(jù)庫(kù)信息來實(shí)現(xiàn)自定義主鍵生成器(優(yōu)點(diǎn):對(duì)數(shù)據(jù)庫(kù)的表只查詢了一次警没,讀取速度相對(duì)于示例1較快):
public class MyGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
// 定義開始字符
String frist = "Chain_";
// 連接對(duì)象
Connection connection = session.connection();
try {
// 數(shù)據(jù)庫(kù)sql語(yǔ)句:查詢表的總數(shù)據(jù)
PreparedStatement ps = connection.prepareStatement("SELECT COUNT(*) AS nextval FROM userinfo");
// 返回結(jié)果集
ResultSet rs = ps.executeQuery();
if (rs.next()) {
// 得到查詢的值+1
int id = rs.getInt("nextval") + 1;
String code = frist + StringUtils.leftPad("" + id, 3, "0");
return code;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
在hibernate.xml里面設(shè)置:
<id name="id" type="java.lang.String">
<column name="ID" />
<generator class="com.zja.hibernate.generator.MyGenerator" />
</id>
13、Hibernate jpa 主鍵策略
Hibernate的主鍵策略jpa都能使用振湾,另外jpa自己也提供了四種主鍵生成策略杀迹。
在jpa中我們可以通過注解@GeneratedValue(strategy=GenerationType.IDENTITY)來設(shè)置主鍵生成策略,但是jpa中的主鍵生成策略有不完美的地方押搪,那就是只能設(shè)置數(shù)值型主鍵的生成策略树酪,而對(duì)于字符串類型的主鍵不能處理浅碾。但是jpa給我們了一個(gè)生成器,實(shí)現(xiàn)jpa規(guī)范的框架可以通過生成器設(shè)置主鍵生成策略嗅回。
jpa 通過注解的方式來配置主鍵生成策略:配置uuid的生成器及穗,生成主鍵的時(shí)候則會(huì)按照此方式生成
@Id
@Column(name="cust_id")
@GenericGenerator(name="my_uuid",strategy="uuid")// 定義一個(gè)生成器
@GeneratedValue(generator="my_uuid")//指定生成器
private String custId;
JPA自己提供了四種的主鍵生成策略:
- AUTO:主鍵由程序控制。
- IDENTITY:主鍵由數(shù)據(jù)庫(kù)自動(dòng)生成(主要是自動(dòng)增長(zhǎng)型)
- SEQUENCE:根據(jù)底層數(shù)據(jù)庫(kù)的序列來生成主鍵绵载,條件是數(shù)據(jù)庫(kù)支持序列埂陆。
- TABLE:使用一個(gè)特定的數(shù)據(jù)庫(kù)表格來保存主鍵。
-
AUTO
默認(rèn)的配置娃豹。如果不指定主鍵生成策略焚虱,默認(rèn)為AUTO。
GenerationType.AUTO:把主鍵生成策略交給持久化引擎(persistence engine),持久化引擎會(huì)根據(jù)數(shù)據(jù)庫(kù)在以上三種主鍵生成策略中選擇其中一種懂版。此種主鍵生成策略比較常用,由于JPA默認(rèn)的生成策略就是GenerationType.AUTO,所以使用此種策略時(shí).可以顯式的指定@GeneratedValue(strategy = GenerationType.AUTO)也可以直接@GeneratedValue鹃栽。例如:
@Id
@GeneratedValue
或
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
- IDENTITY
? 主鍵則由數(shù)據(jù)庫(kù)自動(dòng)維護(hù),使用起來很簡(jiǎn)單躯畴。
GenerationType.IDENTITY:此種主鍵生成策略就是通常所說的主鍵自增長(zhǎng),數(shù)據(jù)庫(kù)在插入數(shù)據(jù)時(shí),會(huì)自動(dòng)給主鍵賦值,比如MYSQL可以在創(chuàng)建表時(shí)聲明"auto_increment" 來指定主鍵自增長(zhǎng)民鼓。該策略在大部分?jǐn)?shù)據(jù)庫(kù)中都提供了支持(指定方法或關(guān)鍵字可能不同),但還是有少數(shù)數(shù)據(jù)庫(kù)不支持,所以可移植性略差。使用自增長(zhǎng)主鍵生成策略是只需要聲明strategy = GenerationType.IDENTITY即可蓬抄。例如:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
-
SEQUENCE
Hibernate同時(shí)也對(duì)JPA進(jìn)行了擴(kuò)展丰嘉,可以在 GeneratedValue 中指定 generator,然后用 GenericGenerator 指定策略來維護(hù)主鍵。
GenerationType.SEQUENCE:在某些數(shù)據(jù)庫(kù)中,不支持主鍵自增長(zhǎng),比如Oracle,其提供了一種叫做"序列(sequence)"的機(jī)制生成主鍵嚷缭。此時(shí),GenerationType.SEQUENCE就可以作為主鍵生成策略饮亏。該策略的不足之處正好與TABLE相反,由于只有部分?jǐn)?shù)據(jù)庫(kù)(Oracle,PostgreSQL,DB2)支持序列對(duì)象,所以該策略一般不應(yīng)用于其他數(shù)據(jù)庫(kù)。類似的,該策略一般與另外一個(gè)注解一起使用@SequenceGenerator,@SequenceGenerator注解指定了生成主鍵的序列.然后JPA會(huì)根據(jù)注解內(nèi)容創(chuàng)建一個(gè)序列(或使用一個(gè)現(xiàn)有的序列)阅爽。如果不指定序列,則會(huì)自動(dòng)生成一個(gè)序列SEQ_GEN_SEQUENCE路幸。例如:
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_sequence")
@SequenceGenerator(name = "id_sequence", initialValue = 1, allocationSize = 1, sequenceName = "ID_SEQUENCE")
private int id;
- TABLE
GenerationType.TABLE:使用一個(gè)特定的數(shù)據(jù)庫(kù)表格來保存主鍵,持久化引擎通過關(guān)系數(shù)據(jù)庫(kù)的一張?zhí)囟ǖ谋砀駚砩芍麈I,這種策略的好處就是不依賴于外部環(huán)境和數(shù)據(jù)庫(kù)的具體實(shí)現(xiàn),在不同數(shù)據(jù)庫(kù)間可以很容易的進(jìn)行移植,但由于其不能充分利用數(shù)據(jù)庫(kù)的特性,所以不會(huì)優(yōu)先使用。該策略一般與另外一個(gè)注解一起使用@TableGenerator,@TableGenerator注解指定了生成主鍵的表(可以在實(shí)體類上指定也可以在主鍵字段或?qū)傩陨现付?,然后JPA將會(huì)根據(jù)注解內(nèi)容自動(dòng)生成一張表作為序列表(或使用現(xiàn)有的序列表)付翁。如果不指定序列表,則會(huì)生成一張默認(rèn)的序列表,表中的列名也是自動(dòng)生成,數(shù)據(jù)庫(kù)上會(huì)生成一張名為sequence的表(SEQ_NAME,SEQ_COUNT)简肴。序列表一般只包含兩個(gè)字段:第一個(gè)字段是該生成策略的名稱,第二個(gè)字段是該關(guān)系表的最大序號(hào),它會(huì)隨著數(shù)據(jù)的插入逐漸累加。例如:
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "id_sequence")
@TableGenerator(name = "id_sequence", allocationSize = 1, table = "sequence_table", pkColumnName = "sequence_max_id", valueColumnName = "sequence_count")
private int id;
補(bǔ)充說明:
@GeneratedValue: 給實(shí)體類生成唯一標(biāo)識(shí)的主鍵(JPA要求實(shí)體Entity,必須有且只有一個(gè)主鍵)百侧。有兩個(gè)屬性着帽,分別是strategy和generator。
generator:默認(rèn)為空字符串移层,定義了主鍵生成器的名稱,對(duì)應(yīng)的生成器有兩個(gè):對(duì)應(yīng)于同名的主鍵生成器@SequenceGenerator和@TableGenerator赫粥。
strategy:一共有四種观话,被定義在枚舉類GenerationType中,包括:TABLE, SEQUENCE, IDENTITY 和AUTO越平。
@GenericGenerator: ** 是HIbernate提供的自定義主鍵策略生成器频蛔,需要和@GeneratedValue**一起使用灵迫,它的name屬性要和@GeneratedValue中的generator名稱要一致。支持13種策略晦溪。
@Id
@GeneratedValue(generator = "myGenerator")
@GenericGenerator(name = "myGenerator", strategy = "uuid")
其中 strategy 有15個(gè)選項(xiàng)(13種策略)瀑粥,分別是
public DefaultIdentifierGeneratorFactory() {
//uuid2特點(diǎn)是:不需要和數(shù)據(jù)庫(kù)交互,可根據(jù)RFC4122定義的5中變量控制具體的生成策略(因?yàn)榉蟁FC4122定義,所以避免了警告信息)
register("uuid2", UUIDGenerator.class);
//guid特點(diǎn)是:需要和數(shù)據(jù)庫(kù)進(jìn)行一次查詢才能生成三圆。數(shù)據(jù)庫(kù)全局唯一狞换。MySQL 用 select uuid();Oracle 用 return "select rawtohex(sys_guid()) from dual";
register("guid", GUIDGenerator.class);
//uuid特點(diǎn):不需要和數(shù)據(jù)庫(kù)交互,全網(wǎng)唯一舟肉。它會(huì)根據(jù)內(nèi)部程序計(jì)算出32位長(zhǎng)度的唯一id
register("uuid", UUIDHexGenerator.class);
register("uuid.hex", UUIDHexGenerator.class);
//hilo特點(diǎn):需要和數(shù)據(jù)庫(kù)交互修噪,全數(shù)據(jù)庫(kù)唯一,與guid不同的是路媚,在標(biāo)識(shí)符的單個(gè)源必須被多個(gè)插入訪問時(shí)可以避免擁堵黄琼。
register("hilo", TableHiLoGenerator.class);
//assigned特點(diǎn):不需要和數(shù)據(jù)庫(kù)交互,自己管理主鍵生成整慎,顯示的指定id脏款。沒有生成邏輯,如果為空就拋出異常裤园。
register("assigned", Assigned.class);
//identity特點(diǎn):需要和數(shù)據(jù)庫(kù)交互撤师,數(shù)據(jù)插入后返回(反查)id,同一列唯一比然。
register("identity", IdentityGenerator.class);
//select特點(diǎn):需要和數(shù)據(jù)庫(kù)交互丈氓。具有和identity類似的行為,有數(shù)據(jù)庫(kù)觸發(fā)器生成强法。
register("select", SelectGenerator.class);
//sequence特點(diǎn):需要和數(shù)據(jù)庫(kù)交互(但不是每次都是)万俗。sequence唯一。通過不同的數(shù)據(jù)庫(kù)饮怯,獲取不同的取值語(yǔ)句 dialect.getSequenceNextValString(sequenceName); 然后進(jìn)行查詢闰歪,緩存到IntegralDataTypeHolder中,通過 generateHolder( session ).makeValue();進(jìn)行獲得.
register("sequence", SequenceGenerator.class);
//seqhilo特點(diǎn):需要和數(shù)據(jù)庫(kù)交互蓖墅,全數(shù)據(jù)庫(kù)唯一库倘,與guid不同的是,在標(biāo)識(shí)符的單個(gè)源必須被多個(gè)插入訪問時(shí)可以避免擁堵论矾。處理邏輯和 hilo 相同教翩,只不過是使用一個(gè)具名的數(shù)據(jù)庫(kù)序列來生成高值部分
register("seqhilo", SequenceHiLoGenerator.class);
//increment特點(diǎn):僅需要首次訪問數(shù)據(jù)庫(kù)。數(shù)據(jù)庫(kù)啟動(dòng)時(shí)查詢表的最大主鍵列支贪壳,并通過 IntegralDataTypeHolder 緩存饱亿。插入一條,它自加一。不適合集群項(xiàng)目彪笼。
register("increment", IncrementGenerator.class);
//foreign特點(diǎn):需要和數(shù)據(jù)庫(kù)訪問钻注。通過給定的 entityName 和 propertyName 查詢獲得值
register("foreign", ForeignGenerator.class);
register("sequence-identity", SequenceIdentityGenerator.class);
register("enhanced-sequence", SequenceStyleGenerator.class);
register("enhanced-table", TableGenerator.class);
}