Spring Data JPA主键违规约束不起作用
Posted
技术标签:
【中文标题】Spring Data JPA主键违规约束不起作用【英文标题】:Spring Data JPA Primary Key Violation Constraint Not Working 【发布时间】:2021-01-31 06:28:21 【问题描述】:代码和配置:
使用的数据库 - 内存数据库中的 H2
用户实体:
@Entity
@Table(name = "users")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable
/**
*
*/
private static final long serialVersionUID = 455202739064202185L;
@Id // please note is not auto generated but manually generated
@Column(name = "id",unique=true)
@NotNull
private long id;
@Column(name = "firstName")
@NotEmpty(message = "First name is required")
private String firstName;
@Column(name = "lastName")
@NotEmpty(message = "Last name is required")
private String lastName;
@Column(name = "email")
@NotEmpty(message = "Email is required")
@Email(message="Email Must be well formed")
private String email;
用户存储库:
public interface UserJpaRepository extends JpaRepository<User, Long>
UserServiceImpl :
this.userJpaRepository.saveAll(users);
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.exostar</groupId>
<artifactId>FileUpload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>FileUpload</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
</project>
问题:
根据用户实体类,手动生成@Id
。
(我有一个 CSV 文件,其中包含在用户实体中读取的 Id 字段)
所以 Id 不是自动生成的
每当我调用 this.userJpaRepository.saveAll(users)
时,即使有一个带有 Id 的 User entity
已经存在,User entity
也会被覆盖。
也就是说,具有相同实体的Id
会被新数据覆盖。
它必须抛出 - Unique index or primary key violation error
但是,当我尝试在 H2 数据库中手动插入 重复条目 时,它会引发异常 - Unique index or primary key violation
我还尝试将unique=true
添加到用户实体中的 Id 字段,但它不起作用
有人可以帮忙解决这个问题吗?
【问题讨论】:
这是因为save()
会在 id 存在时更新。您必须手动检查是否存在 id
【参考方案1】:
事实证明,您看到的行为是因为在 save()
实现中调用了 em.merge(...)
。以下是实际发生的情况:
@Transactional
@Override
public <S extends T> S save(S entity)
Assert.notNull(entity, "Entity must not be null.");
if (entityInformation.isNew(entity))
em.persist(entity);
return entity;
else
return em.merge(entity); // Update if the entity is not new
这是来自SimpleJpaRepository
实现的示例代码。您可以使用自己的查询方法来更新现有查询,如下所示:
@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);
【讨论】:
以上是关于Spring Data JPA主键违规约束不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Spring Data JPA - 查询日期减去 2 天不起作用
Spring Data JPA自定义查询限制功能不起作用[重复]