hibernate的主键生成策略包括那些 (一)

2014-11-24 11:10:39 · 作者: · 浏览: 0

hibernate 主键生成策略有三种:序列 自增 通用
1、序列 sequence
只能在oracle 和 DB2中使用





2、自增 identity
智能在sqlserver 和 mysql 中使用,同时建表的时候,设置列 为 auto increment。



3、通用 native
mysql 就用不了了
这个oracle中必须创建一个名字为 hibernate_sequence的序列。



1、uuid2,IdentifierGenerator的实现类是UUIDGenerator,具体由UUIDGenerationStrategy策略负责生成,它有两个实现StandardRandomStrategy和CustomVersionOneStrategy,他们都是使用java.util.UUID的api生成主键的,StandardRandomStrategy最终由UUID.randomUUID();生成,而CustomVersionOneStrategy则采用版本号与位运算通过构造函数newUUID(mostSignificantBits,leastSignificantBits);生成。
特点是:不需要和数据库交互,可根据RFC4122定义的5中变量控制具体的生成策略

2、guid,IdentifierGenerator的实现类是GUIDGenerator,通过session.getFactory().getDialect().getSelectGUIDString();获得各个数据库中的标示字符串,mySql用"selectuuid()";oracle9g用return"selectrawtohex(sys_guid())fromdual";其他看源码吧。
特点是:需要和数据库进行一次查询才能生成。数据库全局唯一。

3、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()))生成。
特点:不需要和数据库交互,全网唯一。

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

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

6、identity,IdentityGenerator并没有直接实现IdentifierGenerator,而是扩展了AbstractPostInsertGenerator,并实现PostInsertIdentifierGenerator,而PostInsertIdentifierGenerator实现了IdentifierGenerator. 通过IdentifierGeneratorHelper类生成,这个比较特殊,它返回是个常量"POST_INSERT_INDICATOR",指在数据库插入后时生成,然后返回数据库生成的id,还有个常量"SHORT_CIRCUIT_INDICATOR",是用外键ForeignGenerator时使用的。
特点:需要和数据库交互,数据插入后返回(反查)id,同一列唯一

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

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

9、seqhilo,扩展了SequenceGenerator,处理逻辑和hilo相同,值不过是使用一个具名的数据库序列来生成高值部分。
特点:同4

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

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

后面的几种基本上是上面各种逻辑的组合,不在一一分析了。enhanced-table是通过数据库中的表生成id的。


从上面可以看到,虽然这么多,但是大体可以分为三类
1、不需要和数据库交互就可以生成id的。包括uuid,uuid2,uuid.hex
2、需要和数据库交互以生成id的。guid,hilo,identity,select,sequence,seqhilo,increment、foreign
可细分为一个id一个sql:guid,identity,select,foreign
一个sql多个id:hilo,sequence,seqhilo,increment
3、不用交互我自己管理assigned

提高系统新能的主要做法就是显著减少数据库的访问次数。通过上面的分析,可作为我们考虑的一个指标。
大家议论下,自己项目中的主键生成是什么策略,以及优缺点是什么?


这是为csdn的大牛ldh911的议论以下继续
◎ 关于ID生成
—— 我一贯认为入手都是Assigned,也就是说我考虑的方式是:如果我自己来生成这个ID的话,最优选择是啥?然后再看看Hibernate之类的是否能提供我最优选择所期望的。
—— 是否集群环境?是第