JPA Hibernate 主键生成策略

JPA自己提供了四种的主键生成策略:

  • AUTO:主键由程序控制。
  • IDENTITY:主键由数据库自动生成(主要是自动增长型)
  • SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
  • TABLE:使用一个特定的数据库表格来保存主键。

1. AUTO

   默认的配置。如果不指定主键生成策略,默认为AUTO。


@Id  
@GeneratedValue

//或者
@Id
@GeneratedValue(strategy = GenerationType.AUTO)

 

2. IDENTITY

    主键则由数据库自动维护,使用起来很简单。

@Id  
@GeneratedValue(strategy = GenerationType.IDENTITY)  

 

3. SEQUENCE

 

 

 

 

Hibernate同时也对JPA进行了扩展,可以在 GeneratedValue 中指定 generator , 然后用 GenericGenerator 指定策略来维护主键。

@Id
@GeneratedValue(generator = "myGenerator")    
@GenericGenerator(name = "myGenerator", strategy = "uuid")  

 

其中 strategy 有15个选项,分别是

 1 public DefaultIdentifierGeneratorFactory() {    
 2     register("uuid2", UUIDGenerator.class);
 3     register("guid", GUIDGenerator.class);
 4     register("uuid", UUIDHexGenerator.class);
 5     register("uuid.hex", UUIDHexGenerator.class);
 6     register("hilo", TableHiLoGenerator.class);
 7     register("assigned", Assigned.class);
 8     register("identity", IdentityGenerator.class);
 9     register("select", SelectGenerator.class);
10     register("sequence", SequenceGenerator.class);
11     register("seqhilo", SequenceHiLoGenerator.class);
12     register("increment", IncrementGenerator.class);
13     register("foreign", ForeignGenerator.class);
14     register("sequence-identity", SequenceIdentityGenerator.class);
15     register("enhanced-sequence", SequenceStyleGenerator.class);
16     register("enhanced-table", TableGenerator.class);
17 }

 

  • uuid2

IdentifierGenerator 的实现类是 UUIDGenerator,具体由 UUIDGenerationStrategy 策略负责生成,它有两个实现 StandardRandomStrategy 和 CustomVersionOneStrategy,他们都是使用j ava.util.UUID 的 api 生成主键的。

StandardRandomStrategy 最终由 UUID.randomUUID(); 生成;

CustomVersionOneStrategy 则采用版本号与位运算通过构造函数 new UUID(mostSignificantBits,leastSignificantBits); 生成。

特点是:不需要和数据库交互,可根据RFC4122定义的5中变量控制具体的生成策略(因为符合RFC4122定义,所以避免了警告信息)

 

  • guid

IdentifierGenerator 的实现类是 GUIDGenerator,通过 session.getFactory().getDialect().getSelectGUIDString(); 获得各个数据库中的标示字符串.

MySQL 用 select uuid();

Oracle 用 return "select rawtohex(sys_guid()) from dual"; 

特点是:需要和数据库进行一次查询才能生成。数据库全局唯一。

 

  • uuid,uuid.hex

uuid和uuid.hex 两个一个东西。IdentifierGenerator的实现类是UUIDHexGenerator,通过StringBuffer(36).append(format(getIP())).append(sep).append(format(getJVM())).append(sep).append(format(getHiTime())).append(sep).append(format(getLoTime())).append(sep).append(format(getCount()))生成。
特点:不需要和数据库交互,全网唯一。

 

  • hilo

IdentifierGenerator 的实现类 TableHiLoGenerator,逻辑较为复杂,通过高低位酸腐生成,但是需要给定表和列作为高值的源。加上本地的地位计算所得。
特点:需要和数据库交互,全数据库唯一,与guid不同的是,在标识符的单个源必须被多个插入访问时可以避免拥堵。

 

  • assigned

IdentifierGenerator 的实现类 Assigned,没有生成逻辑,如果为空就抛出异常。
特点:不需要和数据库交互,自己管理主键生成,显示的指定id。

 

  • identity

IdentityGenerator 并没有直接实现 IdentifierGenerator,而是扩展了AbstractPostInsertGenerator,并实现PostInsertIdentifierGenerator。
而 PostInsertIdentifierGenerator 实现了 IdentifierGenerator,通过IdentifierGeneratorHelper类生成。
这个比较特殊,它返回是个常量 "POST_INSERT_INDICATOR",指在数据库插入后时生成,然后返回数据库生成的id;
还有个常量 "SHORT_CIRCUIT_INDICATOR",是用外键ForeignGenerator时使用的。

特点:需要和数据库交互,数据插入后返回(反查)id,同一列唯一。

 

  • select

SelectGenerator 扩展了 AbstractPostInsertGenerator 实现了 Configurable 接口,而 AbstractPostInsertGenerator 实现了 PostInsertIdentifierGenerator。所以具有和identity类似的行为,有数据库触发器生成。
特点:需要和数据库交互。

 

  • sequence

SequenceGenerator 实现了 PersistentIdentifierGenerator 接口,和 Configurable 接口。
PersistentIdentifierGenerator 接口扩展 IdentifierGenerator 接口,通过不同的数据库,获取不同的取值语句 dialect.getSequenceNextValString(sequenceName); 然后进行查询,缓存到IntegralDataTypeHolder中,通过 generateHolder( session ).makeValue(); 获得。
特点:需要和数据库交互(但不是每次都是)。sequence唯一。

 

  • seqhilo

seqhilo,扩展了 SequenceGenerator, 处理逻辑和 hilo 相同,值不过是使用一个具名的数据库序列来生成高值部分。
特点:需要和数据库交互,全数据库唯一,与guid不同的是,在标识符的单个源必须被多个插入访问时可以避免拥堵。

 

  • increment

IdentifierGenerator 的实现类 IncrementGenerator,并实现了 Configurable 接口。数据库启动时查询表的最大主键列支,并通过 IntegralDataTypeHolder 缓存。插入一条,它自加一。
特点:仅需要首次访问数据库。

 

  • foreign

IdentifierGenerator 的实现类 ForeignGenerator,通过给定的 entityName 和 propertyName 查询获得值。
特点:需要和数据库访问。

 

 

posted on 2018-12-28 12:07  BadTree  阅读(1224)  评论(0编辑  收藏  举报