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

Spring JPA关联表字段查询报错:派生查询触发StackOverflowError

问题解决:JPA查询栈溢出及关联字段查询方案

问题分析

你遇到的StackOverflowError并非查询方法命名错误——findDiscountContractByExtReferenceIdAndContractTypeType本身符合Spring Data JPA的命名规则,能正确生成查询语句。错误根源是@Data注解自动生成的toString方法:

  • DiscountContract包含懒加载的ContractType关联字段,当Optional调用DiscountContract的toString时,会触发懒加载代理对象的初始化;
  • @Data生成的toString会递归打印关联对象的所有字段,Hibernate代理对象的toString逻辑间接触发了对DiscountContract的引用,形成无限递归,最终导致栈溢出。

解决方案

1. 修复栈溢出问题

在DiscountContract的contractType字段上添加@ToString.Exclude,避免toString递归调用关联对象:

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DiscountContract {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
    @GenericGenerator(name = "native", strategy = "native")
    private Long id;
    private String extReferenceId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "contract_type_id", nullable = false, referencedColumnName = "id")
    @ToString.Exclude // 排除该字段的toString递归
    private ContractType contractType;
}

也可在ContractType类中用@ToString.Exclude标记非必要字段,进一步降低递归风险。

2. SpEL查询实现(可选)

若偏好显式查询语句,可在Repository接口中添加@Query注解实现SpEL查询:

@Repository
public interface DiscountContractRepository extends JpaRepository<DiscountContract, Long> {

    @Query("SELECT dc FROM DiscountContract dc JOIN dc.contractType ct " +
           "WHERE dc.extReferenceId = :extRefId AND ct.type = :type")
    Optional<DiscountContract> findByExtReferenceIdAndContractTypeType(
        @Param("extRefId") String extReferenceId,
        @Param("type") String type
    );
}

这种方式更直观,也能避免过长的方法命名。

验证说明

修复toString递归问题后,原方法命名查询即可正常运行;使用SpEL查询时,需确保参数名与@Param注解一致,避免参数绑定错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 11:22:25