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

Spring Boot3+Hibernate6.5实体双向关联栈溢出问题排查

Spring Boot3(Hibernate6)中Spot与SpotCondition双向关联引发的栈溢出及代理转换异常问题

数据库中Spot和SpotCondition存在双重关联:

  • Spot作为多个SpotCondition的父级,是基础OneToMany关联;
  • 每个Spot通过外键spt_current_condition关联当前的SpotCondition,需实现双向关联。

该逻辑在Spring Boot2.7.1(Hibernate5)中运行正常,但迁移至Spring Boot3(Hibernate6.5)后,查询包含内嵌CurrentSpotCondition的Spot时出现java.lang.StackOverflowError,推测是循环关联导致。


实体类代码

Spot类

@Entity
@Table( name = "t_spot_spt" )
@Data
@NoArgsConstructor
public class Spot {

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Column( name = "spt_id" )
    private Integer             id;

    @OneToOne( fetch = FetchType.EAGER )
    @JoinColumn( name = "spt_current_condition" )
    private SpotCondition       currentCondition;

    @OneToMany( mappedBy = "spot", fetch = FetchType.LAZY )
    private List<SpotCondition> conditions;

    @Column( name = "spt_bla_id" )
    private Integer             bladeId;
}

SpotCondition抽象类

@Entity
@Table( name = "t_spot_condition_scd" )
@Data
@NoArgsConstructor
@ToString( onlyExplicitlyIncluded = true )
public abstract class SpotCondition implements Diffable<SpotCondition> {

    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    @Column( name = "scd_id" )
    @ToString.Include
    protected Integer                       id;

    @ManyToOne( fetch = FetchType.EAGER )
    @JoinColumn( name = "scd_spt_id" )
    protected Spot                          spot;
}

Repository与Service代码

SpotRepository

public interface SpotRepository extends JpaRepository<Spot, Integer> {

    List<Spot> findByBladeId( Integer bladeId );
}

Service核心方法

@Override
@Transactional( readOnly = true )
public Integer findWorstDamageSeverityIdByBlade( Integer bladeId ) {
    short level = Short.MIN_VALUE;
    Integer sevId = null;
    boolean repairPresent = false;
    for ( Spot spt : spotRepository.findByBladeId( bladeId ) ) {
        SpotCondition sc = spt.getCurrentCondition();
        // 执行相关操作
        ... 
    }
}

报错信息

初始栈溢出错误

2024-07-25T21:09:55.332+02:00[0;39m [31mERROR[0;39m [35m19556[0;39m [2m---[0;39m [2m[p-nio-80-exec-6][0;39m [2m[0;39m[36mo.a.c.c.C.[.[.[.[dispatcherServlet]     [0;39m [2m:[0;39m Servlet.service() for servlet [dispatcherServlet] in context with path [/bladeexpert] threw exception [Handler dispatch failed: java.lang.StackOverflowError] with root cause

java.lang.StackOverflowError: null
    at org.hibernate.sql.results.internal.NavigablePathMapToInitializer.get(NavigablePathMapToInitializer.java:33) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
    ...(省略部分栈信息)

修改为LAZY后的警告

2024-07-25T21:30:11.878+02:00[0;39m [33m WARN[0;39m [35m19556[0;39m [2m---[0;39m [2m[p-nio-80-exec-3][0;39m [2m[0;39m[36mo.h.e.i.StatefulPersistenceContext      [0;39m [2m:[0;39m HHH000179: Narrowing proxy to class com.bladeexpert.core.entity.spot.damage.OutdoorDamageSpotCondition - this operation breaks ==

修改后栈溢出问题解决,但无法获取CurrentSpotCondition。


已尝试的操作

将Spot类中currentCondition的@OneToOne获取策略从EAGER改为LAZY,栈溢出问题消失,但出现代理转换警告且无法获取到CurrentSpotCondition。

恳请提供解决思路,感谢帮助!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:44:51