Hibernate自增主键因重复导致报错“Duplicate entry 'xxx' for key 'PRIMARY'”

来源:互联网 发布:美折促销软件 编辑:程序博客网 时间:2024/05/22 13:06

最近项目中的日志文件总是能看到像下面这样的报错信息:

2017-12-13 13:33:31,427 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (Thread-10:) Duplicate entry '1153' for key 'PRIMARY'

最初因为找不到引起改问题的原因,又没法重现,再加上对项目运行没影响,就没去关注。
但今天同样的问题引起业务流程跑不下去了,而且能够成功复现出来,所以得下决心解决了。

问题复现的场景是:多个人对同一张表同时执行插入操作,也就是并发操作。

按理说,主键是在数据库中设置的自增,应该不会因为并发操作导致主键冲突,所以怀疑是Hibernate框架导致的。

主键配置如下:

@Id@GeneratedValue(generator = "system-uuid")   @GenericGenerator(name = "system-uuid", strategy = "increment")@Column(name = "ID", nullable = false)private Long id;

初步推断是Hibernate框架在插入数据库之前就生成好了主键,即主键由Hibernate产生,而非数据库产生。于是上网去搜Hibernate主键生成策略相关的文章,找到下面这段描述:

increment:代理主键,适合于所有数据库,由hibernate维护主键自增,和底层数据库无关,但是不适合于2个或以上hibernate进程。

identity:代理主键,适合于Mysql或ms sql server等支持自增的dbms,主键值不由hibernate维护。

sequence:代理主键,适合于oracle等支持序列的dbms,主键值不由hibernate维护,由序列产生。

native:代理主键,根据底层数据库的具体特性选择适合的主键生成策略,如果是mysql或sqlserver,选择identity,如果是oracle,选择sequence。

hilo:代理主键,hibernate把特定表的字段作为hign值,生成主键值

uuid.hex:代理主键,hibernate采用uuid 128位算法生成基于字符串的主键值

assign:适合于应用程序维护的自然主键。

项目中用到的是“increment”,证明之前的推断是正确的,因为项目用的数据库是MySQL,于是换用“identity”,即:

@Id@GeneratedValue(generator = "system-uuid")   @GenericGenerator(name = "system-uuid", strategy = "identity")@Column(name = "ID", nullable = false)private Long id;

问题成功解决!

参考文章:
http://www.cnblogs.com/flyoung2008/articles/2165759.html

阅读全文
0 0