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

Spring Boot 2.5迁移至3.1.5时Hibernate 6.2报'targetModelPart'为空异常

问题原因分析:Spring Boot 3.1.5(Hibernate 6.2)迁移中的"targetModelPart"空指针异常

问题背景

将遗留应用从Spring Boot 2.5升级到3.1.5后,Hibernate 6.2抛出包含"targetModelPart" is null的空指针异常,关联的一对多映射代码如下:

@JoinColumns({
        @JoinColumn(name = "TICKER_SERIAL", referencedColumnName = "TICKER_SERIAL", insertable = false, updatable = false),
})
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private Set<FundTickerDescription> fundTickerDescriptions;


@JsonProperty("INDEX_BENCHMARK")
@Fetch(FetchMode.JOIN)
@JoinColumn(name = "TICKER_SERIAL", referencedColumnName = "TICKER_SERIAL")
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
private List<FundBenchmarkV2> fundBenchmarkV2s;

异常堆栈核心报错信息:

Suppressed: java.lang.NullPointerException: Cannot invoke "org.hibernate.metamodel.mapping.PropertyBasedMapping.getPropertyAccess()" because "targetModelPart" is null
        at org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor.<init>(SimpleForeignKeyDescriptor.java:130)
        at org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper.interpretPluralAttributeMappingKeyDescriptor(MappingModelCreationHelper.java:784)

问题根源

你提到关联实体TickerDescriptionsV2的ID类被错误标记为@Embeddable,而实际应该是用于@IdClass的普通类,这正是触发异常的核心原因:

  • Hibernate 6.x注解校验更严格:Spring Boot 2.5对应的Hibernate 5.x版本对这类注解错误的容忍度较高,可能不会触发明显异常;但Hibernate 6.2在构建映射元数据时,会严格校验主键类的注解类型,不允许混淆使用。
  • 错误注解导致映射元数据混乱:当ID类被标记为@Embeddable,Hibernate会将其识别为可嵌入组件,而非实体的主键类。在处理一对多关联的外键映射时,无法正确解析目标实体的主键结构,导致targetModelPart无法被初始化,最终触发空指针。
  • 关联映射的连锁影响:异常中涉及的多个一对多关联(如fundBenchmarkV2s、fundTickerDescriptions)都依赖关联实体的主键映射正确性,一旦某个实体的主键注解错误,会连锁影响所有关联的映射初始化流程。

解决方案

修正TickerDescriptionsV2的ID类注解,并调整实体类配置:

  1. 移除ID类上的@Embeddable注解,将其改为普通Java类,确保包含与实体主键字段对应的属性,并重写equals()和hashCode()方法。
  2. 在TickerDescriptionsV2实体类上使用@IdClass注解指定该ID类。

示例代码:

// 修正后的ID类(移除@Embeddable)
public class TickerDescriptionsV2Id implements Serializable {
    private Long tickerSerial;
    // 其他主键字段...

    // 实现equals()和hashCode()方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TickerDescriptionsV2Id that = (TickerDescriptionsV2Id) o;
        return Objects.equals(tickerSerial, that.tickerSerial);
    }

    @Override
    public int hashCode() {
        return Objects.hash(tickerSerial);
    }
}

// 修正后的实体类
@Entity
@IdClass(TickerDescriptionsV2Id.class)
public class TickerDescriptionsV2 {
    @Id
    private Long tickerSerial;
    // 其他字段及关联映射...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:24:49