JPA/Hibernate JpaSystemException:X 实例的标识符从 Y 更改为 Z

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

我正在将 Spring Boot 应用程序从 Java 11 更新到 Java 17,并将 Spring Boot

2.7.18
更新到
3.2.4
,并运行测试时出现错误。

所以,我有一个名为

WorkloadDAO
的实体,如下所示:

@Entity
@Table(name = "workloads")
@IdClass(WorkloadId.class)
public class WorkloadDAO {

  @Id
  @NonNull()
  private String id;
  
  @Id
  @Column(name = "created_at", insertable = false, updatable = false, columnDefinition = "TIMESTAMP")
  private LocalDateTime createdAt;

  // more attributes

  @PrePersist
  protected void onCreate() {
    createdAt = LocalDateTime.now();
  }

createdAt
属性将始终以空值接收,并且在将实例保存到数据库之前,将通过用
onCreate()
注释的
@PrePersist
方法设置它。

正如您在注释

@IdClass(WorkloadId.class)
中看到的那样,我将
WorkloadId
设置为此类的id。
WorkloadId
类是这样的:

public class WorkloadId implements Serializable {

  private String id;
  private LocalDateTime createdAt;
}

到目前为止,在测试之前一切都很好。 例如,我正在运行这个测试:

  @Test
  void testSaveWorkload() {
    String id = "someid";
    WorkloadDAO dao = WorkloadDAO.builder()
        .id(id)
        .build();

    WorkloadDAO response = repository.saveAndFlush(dao);

    assertThat(repository.findById(WorkloadId.builder()
            .id(id)
            .createdAt(response.getCreatedAt())
            .build()))
        .get()
        .extracting("createdAt").isNotNull();
  }

在更新Java和Spring Boot之前,此测试运行成功。但现在,我收到以下错误:

org.springframework.orm.jpa.JpaSystemException: identifier of an instance of com.adevinta.delivery.workloadapi.data.WorkloadDAO was altered from WorkloadId(id=someid, createdAt=2024-03-28T12:26:34.355098) to WorkloadId(id=someid, createdAt=null)

你能帮我理解为什么我会得到这个吗? 谢谢!

我期望发生的是测试工作,无需事先设置字段

createdAt

java spring-boot hibernate jpa java-17
1个回答
0
投票

您的问题是由于createdAt上的

insertable = false
属性造成的。
@PrePersist
中分配的值将不会作为结果保存到数据库中。通常,“创建于”字段可插入但不可更新,“修改于”字段反之亦然。尝试将createdAt列定义更改为:

@Column(name = "created_at", insertable = true, updatable = false, columnDefinition = "TIMESTAMP")
.

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