最近研究了一下java后端框架Springboot,在存储时候使用了JPA,然后坑就来了。。。
数据库存储少不了的就是主键,JPA提供多种主键生成方式,至于怎么用,网上一搜很多。这篇文章主要讲自增主键。
一般自增长的主键直接用@GeneratedValue这个注解就可以,默认就是AUTO的自增主键。
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
等同于
@GeneratedValue
private int id;
这种方式生成的主键就是自增长的。但是问题来了,如果我清空数据库,并且想把主键重置到1开始怎么办?
网上搜索了下,发现MYSQL truncate table_name 可以清空数据库,并且重置主键,OK,试了一下,然后重新添加一条数据,发现。。。。
id还是接着上次清除后的值继续增长!!!!
然后还有说用alter这个方法的,同样不靠谱。。。
没办法,只能drop表重新创建试试了,结果发现。。。依然不好使。。。
事已至此,重建表都不能重置这个ID,说明这个ID应该不是MYSQL能左右的了,因此基本可以断定是JPA框架内部操作的。
检测了一下表中ID的属性,发现Auto Increment并没有被勾选

MYSQL Workbench中查看ID的属性
到此已经定罪了,是JPA的问题。。
翻看了一下JPA主键生成的策略:
- TABLE:使用一个特定的数据库表格来保存主键。
- SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
- IDENTITY:主键由数据库自动生成(主要是自动增长型)
- AUTO:主键由程序控制。
发现使用IDENTITY这个策略,就是由数据库生成的主键了,因此尝试把注解修改为
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
发现这样就可以通过重置MYSQL的主键来解决问题了。。。到此可以得到一种解决方案。。
当然我们还想知道JPA控制的主键怎么重置。既然这个主键不受表的限制,因此确定不可能是与表同步的数据,然后又检测了一下配置文件,发现也没有设置过相关参数。
最后在数据库中发现了一个叫做 hibernate_sequence 的表

hibernate_sequence
这个表并不是我手动建的,因此应该是Springboot和JPA自行创建的表,打开发现其中只有一个元素:
next_val
数值就是下次插入的ID值。。。
因此尝试修改生成策略为AUTO,drop这个表之后,再次运行程序,重新创建的表中next-val值是1。
重新插入一条数据,ID为1,问题解决。。。
原创文章,转载请注明出处,谢谢合作~
//www.greatytc.com/p/c7bd1cfacd3d
