You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3.4.0升级后JPA/Hibernate集成测试失败求助

问题描述

将Spring Boot从3.3.6升级至3.4.0后,涉及Hibernate/JPA交互(基于spring-data-jpa)的@SpringBootTest集成测试突然失败。

测试代码片段

@Test
void retrieveAllFahrzeugbewegungenByMuster() throws Exception {
    // Given
    var musterEntity = MusterMetadatenGenerator.createDefaultMuster();
    var musterEntitySaved = musterMetadatenRepository.saveAndFlush(musterEntity); // 此处报错
...
}

实体创建核心逻辑

static <E extends BaseEntity> E createDefaultValues(
      @NotNull final E source,
      @NotNull final LocalDate datumAb,
      @NotNull final LocalDate datumBis
) {
    final Instant now = Instant.now();

    source.setId(UUID.randomUUID());
    source.setDatumAb(datumAb);
    source.setDatumBis(datumBis);
    source.setBearbeitetAm(now);
    source.setErstelltAm(now);

    return source;
}

父类实体定义

@Data
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
public class BaseEntity {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(updatable = false, nullable = false)
  protected UUID id;
...
}

抛出的异常信息

org.springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [de.muster.jpa.entity.MusterMetadaten#40add996-a1f9-43f7-a157-cf5692e5ea65]
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [de.muster.jpa.entity.MusterMetadaten#40add996-a1f9-43f7-a157-cf5692e5ea65]

Spring Boot 3.4.0对应Hibernate 6.6.x,之前版本为Hibernate 6.5.x,询问是否存在破坏性变更导致该问题。


问题原因与解决方案

这是Hibernate 6.6.x的破坏性变更导致的,核心问题出在UUID主键配合GenerationType.AUTO的状态校验逻辑上:

在Hibernate 6.5及更早版本中,手动设置UUID主键值后,Hibernate会默认执行INSERT操作(因为数据库中无对应ID记录);但Hibernate 6.6.x收紧了规则:当手动设置了@GeneratedValue标注的主键值时,Hibernate会判定该实体为** detached 状态**(认为它已持久化但当前不在Session中),执行saveAndFlush时会尝试UPDATE操作,而数据库中没有对应记录,最终触发StaleObjectStateException。

两种修复方案

  1. 修改主键生成策略:将GenerationType.AUTO改为GenerationType.UUID,明确指定UUID生成逻辑,让Hibernate正确识别手动设置的ID:
@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(updatable = false, nullable = false)
protected UUID id;
  1. 移除手动设置ID的逻辑:让Hibernate自动生成UUID主键,saveAndFlush会正常执行INSERT操作:
// 移除测试代码中手动设置ID的行
// source.setId(UUID.randomUUID());

补充说明

Hibernate 6.6.x的这次变更属于对JPA规范的严格遵循,之前版本对"手动设置自动生成主键"的场景存在逻辑宽松,新版本收紧规则后,原有不符合规范的代码触发了异常。

内容的提问来源于stack exchange,提问作者kladderradatsch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:03:26