JPA使用Hibernate实现,使用UUID.主键的生成策略.

警告信息以下: java

3.1 WARN  [org.hibernate.id.UUIDHexGenerator] (ServerService Thread Pool -- 48) HHH000409:Using org.hibernate.id.UUIDHexGenerator which does not generate IETF RFC 4122 compliant UUID values; consider using org.hibernate.id.UUIDGenerator instead sql

修改 @GenericGenerator(name = "system-uuid", strategy = "uuid") 为@GenericGenerator(name = "system-uuid", strategy = "uuid2") 数据库

下面是在CSDN上看到的一篇文章,保存在个人txt中,如今也贴出来. api

介绍hibernate主键生成策略的文章网上比比皆是。可是如何选择一个适合于本身项目的主键生成策略缺没有什么好的指导性文章。在此但愿与你们议论。 
hibernate的主键生成策略主要包括了"uuid2","guid","uuid","uuid.hex","hilo","assigned","identity","select","sequence","seqhilo","increment","foreign","sequence-identity","enhanced-sequence","enhanced-table",所有在org.hibernate.id.factory.DefaultIdentifierGeneratorFactory中定义,至于每种生成策略的简单描述不是本文重点议论的话题,咱们主要将着眼点放到各生成器的优缺点上去(固然都有优势只是适合不适合,本文就想议论这个)
hibernate主键生成采用策略模式进行设计,各个生成策略都直接或或者间接实现了IdentifierGenerator接口,此接口只有一个方法publicSerializablegenerate(SessionImplementorsession,Objectobject)throwsHibernateException;这个方法由各个类实现具体的生成逻辑。
咱们来一个一个看一下: 缓存

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

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

三、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,逻辑较为复杂,经过高低位酸腐生成,可是须要给定表和列做为高值的源。加上本地的地位计算所得。复杂有兴趣看"数据建模101"(Ambler,2002)
特色;须要和数据库交互,全数据库惟一,与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,扩展了SequenceGenerator,处理逻辑和hilo相同,值不过是使用一个具名的数据库序列来生成高值部分。 
特色:同4 

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

十一、foreign,IdentifierGenerator的实现类ForeignGenerator,经过给定的entityName和propertyName查询得到值。
特色:须要和数据库访问。 

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

从上面能够看到,虽然这么多,可是大致能够分为三类 
一、不须要和数据库交互就能够生成id的。包括uuid,uuid2,uuid.hex 
二、须要和数据库交互以生成id的。guid,hilo,identity,select,sequence,seqhilo,increment、foreign 
  可细分为一个id一个sql:guid,identity,select,foreign 
  一个sql多个id:hilo,sequence,seqhilo,increment 
三、不用交互我本身管理assigned 

提升系统新能的主要作法就是显著减小数据库的访问次数。经过上面的分析,可做为咱们考虑的一个指标。 
你们议论下,本身项目中的主键生成是什么策略,以及优缺点是什么? 

这是为csdn的大牛ldh911的议论如下继续 
◎ 关于ID生成 
—— 我一向认为入手都是Assigned,也就是说我考虑的方式是:若是我本身来生成这个ID的话,最优选择是啥?而后再看看Hibernate之类的是否能提供我最优选择所指望的。
—— 是否集群环境?是第一个要考虑的因素,但基本上我都以集群环境为必要条件; 
—— 而后是:超高并发生成?超高并发查询?ID是否须要存在语义?等问题。 

◎ 不一样的ID对我来讲有啥区别? 
—— UUID:极其适用于分布式计算环境(超越集群了),但ID将不能承载任何语义,高并发生成支持较好,超高并发查询存在数据库端不易优化的问题。
—— 数据库端seq:适用于集群环境,ID可承载某些语义(好比生成时间上较大范围的前后顺序),超高并发生成较搓,超高并发查询可作特定分区优化。 

◎ 最终呢? 
—— 最终基本上都选择UUID或其变体,由于有时候我仍是须要ID承载少许语义的,好比我可能会关心这个UUID到底是哪一个终端生成的,你可能会说:能够换个字段保存啊?这类问题就智者见智仁者见仁了。 session

相关文章
相关标签/搜索