Hibernate提供的主鍵生成策略,使我們可以在實體類的映射xml文件中設定關鍵字來告訴hibernate我們要使用的主鍵生成方式,然後hibernate會根據設定完成數據庫的主鍵控制。
一、首先通過舉例子來了解實體映射文件(*.hbm.xml)中對id生成策略配置格式
用戶User的實體類User.java
package com.bjpowernode.hibernate;
import java.util.Date;
public class User {
private String id;
private String name;
public User(){}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
User.java對應的映射文件User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.User">
<id name="id">
<generator class="uuid"/>
</id>
<property name="name"/>
<property name="password"/>
</class>
</hibernate-mapping>
其中
<id name="id" column="表主鍵字段名" type="java.lang.Integer">
<generator class="設置主鍵生成策略類型"/>
</id>
二、Hibernate常用的主鍵生成策略的原理、特點、應用場合
關於映射文件的問題下次再介紹,這次主要總結hibernate常用主鍵生成策略。
(1)increment
a)對主鍵值採取自動順序增長的方式生成新的主鍵,值默認從1開始。
b)原理:在當前應用實例中維持一個變量,以保存當前最大值,之後每次需要生成主鍵值的時候將此值加1作爲主鍵.不依賴於底層的數據庫,因此所有的數據庫都可以使用
c)缺點:通過increment的生成主鍵的原理可推斷,此種主鍵生成策略不適用於集羣、同一時段大量用戶併發訪問的系統,既當大量用戶同一時間段同時進行插入操作的時候,可能存在取得相同的最大值然後再同時+1的情況,這個時候就會造成主鍵衝突。因此,如果同一數據庫有多個實例訪問,此方式必須避免使用。
(2)UUID
a)原理UUID使用128位UUID算法生成主鍵,能夠保證網絡環境下的主鍵唯一性,也就能夠保證在不同數據庫及不同服務器下主鍵的唯一性。所以使用於所有數據庫。
b)特點;能夠保證數據庫中的主鍵唯一性,但是在生成的主鍵佔用比較多的存貯空間
(3)Hilo
a)原理:通過hi/lo 算法(Hilo使用高低位算法生成主鍵,高低位算法使用一個高位值和一個低位值,然後把算法得到的兩個值拼接起來)實現的主鍵生成機制,需要額外的數據庫表保存主鍵生成歷史狀態。
b)特點:需要額外的數據庫表和字段提供高位值來源。默認情況下使用的表是 hibernate_unique_key,默認字段叫作next_hi。next_hi必須有一條記錄否則會出現錯誤。需要額外的數據庫表的支持,能保證同一個數據庫中主鍵的唯一性,但不能保證多個數據庫之間主鍵的唯一性。Hilo主鍵生成方式由Hibernate 維護,所以Hilo方式與底層數據庫無關。
(4)sequence
a)sequence實際是就是一張單行單列的表。
b)實現原理:調用數據庫中底層存在的sequence生成主鍵,需要底層數據庫的支持序列,因此他是依賴於數據庫的。
c)支持sequence的數據庫有:Oracle 、DB2(Mysql/SQlServer不支持)、PostgreSql、SAPDb等
(5)identity
a)根據底層數據庫,來支持自動增長,不同的數據庫用不同的主鍵增長方式。
b)特點: 與底層數據庫有關,要求數據庫支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity。支持的數據庫有MySql、SQL Server、DB2、Sybase和HypersonicSQL。
c)好處:在建表的時候指定了id爲自動增長,實際開發中就不需要自己定義插入數據庫的主鍵值,系統會自動順序遞增一個值 。Identity無需Hibernate和用戶的干涉,使用較爲方便,但由於依賴於數據庫,所以不便於在不同的數據庫之間移植程序。
(6)native
a)作用:根據數據庫的類型,自動在sequence 、identity和,hilo進行切換。
b)實現自動切換的依據:根據Hibernate配置文件中的方言來判斷是Oracle還是Mysql、SqlServer,然後針對數據庫的類型抉擇 sequence還是identity作爲主鍵生成策略。
c)用處:由於Hibernate會根據底層數據庫採用不同的映射方式,因此靈活性高,便於程序移植,項目中如果用到多個數據庫時,可以使用這種方式。
(7)assigned
a)作用:用於手工分配主鍵生成器,一旦指定爲這個了,Hibernate就不在自動爲程序做主鍵生成器了。沒有指定<generator>標籤時,默認就是assigned主鍵的生成方式
b)使用方法:在程序中session.save();之前,由程序員自己指定主鍵值爲多少。
例如:user.setId(1);這就是在程序中程序員手動爲用戶表指定主鍵值爲1。
(8)foreign
只適用基於共享主鍵的一對一關聯映射的時候使用。即一個對象的主鍵是參照的另一張表的主鍵生成的。
對數據庫的依賴性總結
UUID,increment、Hilo、assigned:對數據庫無依賴
identity:依賴Mysql或sql server,主鍵值不由hibernate維護
sequence:適合於oracle等支持序列的dbms,主鍵值不由hibernate維護,由序列產生。
native:根據底層數據庫的具體特性選擇適合的主鍵生成策略,如果是mysql或sqlserver,選擇identity,如果是oracle,選擇sequence。
關於主鍵生成策略的選擇:
一般來說推薦UUID,因爲生成主鍵唯一,且對數據庫無依賴,可移植性強。
由於常用的數據庫,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主鍵生成機制(Auto-Increase 字段或者Sequence)。我們可以在數據庫提供的主鍵生成機制上,採用native,sequence或者identity的主鍵生成方式。
不過值得注意的是,一些數據庫提供的主鍵生成機制在效率上未必最佳大量併發insert數據時可能會引起表之間的互鎖。
因此,對於併發Insert要求較高的系統,推薦採用uuid作爲主鍵生成機制。
總之,hibernate主鍵生成器選擇,還要具體情況具體分析。一般而言,利用uuid方式生成主鍵將提供最好的性能和數據庫平臺適應性。