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

本文介绍了一种在使用Hibernate框架时出现的主键冲突问题及其解决方案。问题发生在多用户并发插入相同表时,通过调整主键生成策略从increment改为identity成功解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

### 解决 MySQL 复合主键 `Duplicate entry for key` 错误 当遇到复合主键导致重复条目错误时,通常是因为数据插入过程中违反了唯一约束条件。为了有效解决问题,可以从以下几个方面入手: #### 1. 数据验证与清理 确保要插入的数据不包含任何已经存在的组合值。可以通过查询现有记录来确认是否存在冲突。 ```sql SELECT * FROM your_table WHERE columnA = 'valueA' AND columnB = 'valueB'; ``` 如果发现有重复项,则需要先处理这些异常数据[^1]。 #### 2. 修改应用程序逻辑 检查并调整应用层代码中的业务逻辑,防止同一事务内多次提交相同的关键字段组合。对于批量操作尤其要注意控制好并发情况下的幂等问题[^2]。 #### 3. 设置合适的索引策略 合理设计表结构,在定义复合主键的同时考虑是否还需要额外创建唯一性索引来辅助快速查找和避免重复录入。注意区分哪些列应该参与构成联合索引以及它们之间的顺序关系。 #### 4. 使用 ON DUPLICATE KEY UPDATE 或 INSERT IGNORE 针对某些特定场景可以采用这两种方式之一来进行优雅降级处理: - **ON DUPLICATE KEY UPDATE**: 当发生主键/唯一键冲突时更新已存在行的部分字段; - **INSERT IGNORE**: 忽略那些会引发重复键错误的新纪录而不抛出异常; 示例语法如下所示: ```sql -- 使用 ON DUPLICATE KEY UPDATE 更新已有记录 INSERT INTO table_name (column_list) VALUES(value_list) ON DUPLICATE KEY UPDATE col_to_update=value; -- 使用 INSERT IGNORE 跳过重复记录 INSERT IGNORE INTO table_name (column_list) VALUES(value_list); ``` 通过上述方法能够有效地减少乃至消除因复合主键引起的重复条目问题,从而保障数据库的一致性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值