JPA generatedValue 生成了一个已经存在的 Id

问题描述 投票:0回答:1

我正在开发一个使用 JPA 的 Spring 应用程序。具体来说,为了生成实体的 id,我使用

@GeneratedValue
注释。例如:

@Entity
public class SomeEntity {
  @Id
  @GeneratedValue
  private Long id;
  
  private String someField;

  // Getters and Setters...
}

问题是,我正在将数据预加载到数据库中。例如,在

someFile.sql
中,我有常规的
INSERT
语句:

INSERT INTO some_entity (id, some_field) VALUES (1, 'foo');
INSERT INTO some_entity (id, some_field) VALUES (2, 'bar');
...

然后,我只是使用mysql命令行客户端插入数据:

mysql someDB < someFile.sql

问题是,当尝试使用 JPA 持久化新实体时,将分配的第一个 id 是

1
。然而,该 ID 已被我预加载到数据库的实体之一使用。这样,我收到重复键错误:

2020-07-04 16:08:42.365 错误 847 --- [https-jsse-nio-8080-exec-9] o.h.engine.jdbc.spi.SqlExceptionHelper:键“PRIMARY”的重复条目“1”

我考虑过使用带有

@SequenceGenerator
的初始值。但是,如果我想要预加载的初始值数量增加,这种方法可能会导致必须更改代码。

有什么不同方法的想法吗?

java jpa spring-data-jpa jpa-2.0
1个回答
1
投票

嗯,最简单的解决方案是让脚本本身为下一个生成的 id 建立正确的值。

如果您使用 Hibernate <5 or Hibernate 5 with

hibernate.id.new_generator_mappings=false
,您的设置将导致
id
成为
AUTO_INCREMENT
列。在这种情况下,只需添加

ALTER TABLE some_entity AUTO_INCREMENT = <last_inserted_id>

在脚本的末尾。或者,更好的是,如果可能的话,尝试完全摆脱硬编码的 id 值。您可以使用

LAST_INSERT_ID()
检索最后插入的 ID,并使用该值在相关行中设置外键列。

另一方面,如果您在没有任何特殊配置的情况下使用 Hibernate 5,则应该在架构中找到一个

hibernate_sequence
表,其中存储 Hibernate 将使用的下一个生成的 id。您需要添加以下内容:

UPDATE hibernate_sequence SET next_val= <max_inserted_id_for_any_table_plus_one>

顺便说一句,如果您意外使用后一种方法,您可能需要切换到前一种方法

© www.soinside.com 2019 - 2024. All rights reserved.