目录
一、背景
二、原因分析
三、解决方案
一、背景
JPA1.0版本主键生成策略有4种,如图,包括TABLE、SEQUENCE、IDENTITY、AUTO。本文重点关注TABLE策略和AUTO策略。
图 JPA1.0版本主键生成策略
关于AUTO策略的解释:持久化提供商(因为项目用的是Hibernate,其实说得也就是Hibernate) 会根据数据库类型使用不同的策略。
关于TABLE策略的解释:使用一个特定的数据库表格来保存主键,持久化引擎通过关系数据库的一张特定的表格来生成主键,这种策略的好处就是不依赖于外部环境和数据库具体实现,在不同数据库间可以很容易的进行移植,但由于其不能充分利用数据库的特性,所以不会优先使用。因为这种方法需要大量数据库查询和悲观锁来生成唯一值,并且多个表将可能共享自增id导致混乱。
二、原因分析
JPA数据库主键生成注解策略,@GeneratedValue(strategy = GenerationType.AUTO),在sqlserver-2016 express版本数据库下,频发性报错,报错内容如下:
报错:o.hibernate.id.enhanced.TableStructure : could not read a hi value。
意为:id标识符生成异常,不能读取一个hi值,需要去增加表hibernate_sequence。
根据JPA1.0对TABLE策略的解释,并经过sqlserver数据库环境下取证,Hibernate针对sqlserver-2016express版本,默认id生成策略为TABLE策略。hibernate使用数据库表hibernate_sequence来维护和分配主键,如图:
图 Hibernate维护和分配主键策略
由上述分析,总结可能的原因如下:
原因1:可能是生产环境未成功生成维护主键的表。该原因发生概率较小,毕竟Hibernate5是一个很成熟的库了,而且创建用于维护主键的表,是和数据库交互的一个前置操作,基本不可能。
原因2:可能是主键产生异常。鉴于网络上众多踩坑人的总结,以及该策略本身固有的局限性,该原因发生概率较大。
三、解决方案
决定放弃AUTO策略,选择一种新的可以适配多数据库的主键生成策略,使用雪花算法生成表主键。
目前已经删除国际化sqlserver数据库的表,并使用oneKeyStop.bat和oneKeyStart.bat执行一键停止服务、一键启动服务,反复验证3次,未出现问题。



