Hibernate 和 JPA主鍵生成策略

主鍵生成策略目錄.png
主鍵生成策略.png

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列為例):

  1. 獲得hi值:讀取并記錄數(shù)據(jù)庫(kù)的hibernate_hilo表中next_hi字段的值节预,數(shù)據(jù)庫(kù)中此字段值加1保存叶摄。

  2. 獲得lo值:從0到max_lo循環(huán)取值,差值為1安拟,當(dāng)值為max_lo值時(shí),重新獲取hi值宵喂,然后lo值繼續(xù)從0到max_lo循環(huán)糠赦。

  3. 根據(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ù)表格來保存主鍵。
  1. 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)

  1. 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)  

  1. 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;

  1. 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);
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市配猫,隨后出現(xiàn)的幾起案子幅恋,更是在濱河造成了極大的恐慌,老刑警劉巖泵肄,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捆交,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡凡伊,警方通過查閱死者的電腦和手機(jī)零渐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來系忙,“玉大人诵盼,你說我怎么就攤上這事∫梗” “怎么了风宁?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蛹疯。 經(jīng)常有香客問我戒财,道長(zhǎng),這世上最難降的妖魔是什么捺弦? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任饮寞,我火速辦了婚禮,結(jié)果婚禮上列吼,老公的妹妹穿的比我還像新娘幽崩。我一直安慰自己,他們只是感情好寞钥,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布慌申。 她就那樣靜靜地躺著,像睡著了一般理郑。 火紅的嫁衣襯著肌膚如雪蹄溉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天您炉,我揣著相機(jī)與錄音柒爵,去河邊找鬼。 笑死赚爵,一個(gè)胖子當(dāng)著我的面吹牛餐弱,可吹牛的內(nèi)容都是我干的宴霸。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼膏蚓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了畸写?” 一聲冷哼從身側(cè)響起驮瞧,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎枯芬,沒想到半個(gè)月后论笔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡千所,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年狂魔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淫痰。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡最楷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出待错,到底是詐尸還是另有隱情籽孙,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布火俄,位于F島的核電站犯建,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瓜客。R本人自食惡果不足惜适瓦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谱仪。 院中可真熱鬧玻熙,春花似錦、人聲如沸芽卿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)卸例。三九已至称杨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筷转,已是汗流浹背姑原。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呜舒,地道東北人锭汛。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親唤殴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子般婆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361