SpringDataJpa-主键生成策略

一、SpringDataJpa标准用法

spring data jpa 的标准主键生成策略主要有四种,分别是:

public enum GenerationType {
    TABLE, //使用一个额外的数据库表来保存主键
    SEQUENCE,//使用序列的方式,且其底层数据库要支持序列,一般有postgres、Oracle等
    IDENTITY,//主键由数据库生成,一般为自增型主键,支持的有MySql和Sql Server
    AUTO//由程序来决定主键规则
}

主键的生成规则主要由注解 @GeneratedValue 来说明,其源码如下:

@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface GeneratedValue {
    GenerationType strategy() default AUTO;
    String generator() default "";
}
@Id  
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="payablemoney_seq")  
@SequenceGenerator(name="payablemoney_seq", sequenceName="seq_payment")  

使用的具体例子为:
假设有一个表示人脸图片集合的类为FaceSet,其主键为facesetToken,则表示如下

@Entity(name = "face_set")
public class FaceSet{
}
  • Sequence
    @SequenceGenerator 中的 sequenceName 为序列的名称,需要与@GeneratedValue 中的generator对应
  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE,generator="faceset_generator")
  @SequenceGenerator(name="faceset_generator", sequenceName="faceset_seq")
  @Column(name = "faceset_token", unique = true)
  private String facesetToken;
  • Auto
    如果不指定具体的生成规则,则默认为AUTO,即下列两种情况等价
@Id  
@GeneratedValue(strategy = GenerationType.AUTO) 
private String facesetToken;
@Id  
private String facesetToken;

二、Hibernate主键策略生成

hibernate-5.0.12.Final版本的默认工厂中有14种生成策略,具体可见org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory

    public DefaultIdentifierGeneratorFactory() {
        register( "uuid2", UUIDGenerator.class );
        register( "guid", GUIDGenerator.class );            // can be done with UUIDGenerator + strategy
        register( "uuid", UUIDHexGenerator.class );         // "deprecated" for new use
        register( "uuid.hex", UUIDHexGenerator.class );     // uuid.hex is deprecated
        register( "assigned", Assigned.class );
        register( "identity", IdentityGenerator.class );
        register( "select", SelectGenerator.class );
        register( "sequence", SequenceStyleGenerator.class );
        register( "seqhilo", SequenceHiLoGenerator.class );
        register( "increment", IncrementGenerator.class );
        register( "foreign", ForeignGenerator.class );
        register( "sequence-identity", SequenceIdentityGenerator.class );
        register( "enhanced-sequence", SequenceStyleGenerator.class );
        register( "enhanced-table", TableGenerator.class );
    }

    public void register(String strategy, Class generatorClass) {
        LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );
        final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass );
        if ( previous != null ) {
            LOG.debugf( "    - overriding [%s]", previous.getName() );
        }
    }

对几种比较常用的类型进行说明:

  • uuid
    采用128位的uuid算法生成主键,uuid被编码为一个32位16进制数字的字符串。
    当使用strategy为uuid时,使用的时hibernate自己定义的UUID生成算法,此策略已过时,其具体实现参照org.hibernate.id. UUIDHexGenerator, 生成的字符串如402880876359adeb016359ae27190000
    当使用strategy为uuid2时,此为此版本推荐使用的uuid生成算法,其默认采用标准的生成策略StandardRandomStrategy,实现为使用jdk自带的uuid生成方法,生成的字符串如
    4af17c8e-8317-43e9-aff9-12d5590a71c6
@Id
@GeneratedValue(generator = "faceset_generator")
@GenericGenerator(name = "faceset_generator", strategy = "uuid")
  • assigned
    插入主键时,由程序来指定。相当于JPA中的AUTO。
@Id
@GeneratedValue(generator = "faceset_generator")
@GenericGenerator(name = "faceset_generator", strategy = "assigned")

  • sequence
@Id
@GeneratedValue(generator = "faceset_generator")  
@GenericGenerator(name = "faceset_generator", strategy = "sequence",   
         parameters = { @Parameter(name = "sequence", value = "faceset_seq") }) 
  • guid
    采用数据库底层的guid算法机制,对应MYSQL的uuid()函数,SQL Server的newid()函数,ORACLE的rawtohex(sys_guid())函数等

三、通过@GenericGenerator自定义主键生成策略

常用数据库支持生成规则如下:

数据库 支持的策略
Postgres GenerationType.TABLE
GenerationType.AUTO
GenerationType.IDENTITY
GenerationType.SEQUENCE
Oracle GenerationType.TABLE
GenerationType.AUTO
GenerationType.SEQUENCE
不支持GenerationType.IDENTITY
Mysql GenerationType.TABLE
GenerationType.AUTO
GenerationType.IDENTITY
不支持GenerationType.SEQUENCE
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • class 可配置项 native:根据使用的数据库帮你选择哪个值 uuid:类似C#Guid 1、assigne...
    垃圾简书_吃枣药丸阅读 502评论 0 2
  • 之前在用Hibernate框架写东西的时候,经常会去写映射文件hbm.xml。但是对于主键id的一个generat...
    雅俗共赏M阅读 817评论 0 2
  • 2017年8月21日 我原本只想简单记录一下springboot中应用Jpa的简单操作。不想由于hibernate...
    行者N阅读 6,476评论 0 23
  • 夜色阑珊 霓虹闪烁映窗幔 奢靡的乐声 空气中弥漫着暧昧 那一句三字组成的话语 轻轻萦绕耳畔 万籁俱寂的深宵 回味罗...
    艺腾阅读 236评论 1 7
  • 作者:五年级/钟梓柔 从小到大,我尝过许多滋味,可让我印象最深刻的滋味是——冤枉。 在一个风和日丽的...
    玻璃泡沫阅读 239评论 0 0