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

如何在Repository单元测试中模拟Lombok @Data引发的栈溢出错误

JPA双向关联+Lombok @Data栈溢出的测试验证方案

问题根源

@Data注解会自动生成equals()、hashCode()和toString()方法,而你的实体存在双向关联:

  • UserEntity ↔ HometownEntity(一对多双向)
  • UserEntity ↔ HobbyAndInterestEntity(多对多双向)

这些自动生成的方法会触发循环调用:比如User的toString调用Hometown的toString,后者又调回User的toString,无限递归直接撑爆调用栈,抛出StackOverflowError。

编写测试验证异常场景

你可以写一个测试,主动触发会引发递归的方法,验证用@Data时会抛出异常,换成@Getter+@Setter时测试正常通过。

测试代码示例

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertThrows;

@Test
void testStackOverflowWithDataAnnotation() {
    // 先保存测试数据
    UserEntity savedUser = saveUserEntity();
    // 从仓库加载实体,确保关联关系被初始化(LAZY类型需手动触发加载)
    UserEntity loadedUser = userRepository.findById(savedUser.getId()).orElseThrow();
    
    // 触发toString(),触发双向关联的递归调用
    assertThrows(StackOverflowError.class, loadedUser::toString);
    
    // 若业务场景用到equals/hashCode,也可补充对应测试
    // assertThrows(StackOverflowError.class, () -> loadedUser.equals(loadedUser));
}

注意事项

  1. 处理LAZY加载:如果关联是LAZY fetch类型,需要先调用关联字段的get方法(比如loadedUser.getHometownEntity().getCity()),确保关联实体被加载,否则递归不会立即触发。
  2. 验证修复效果:当你把实体的@Data替换成@Getter+@Setter,或者用@Data但给关联字段加排除注解,这个测试就不会再抛出异常,证明修复有效。

可选修复方案

要是想继续用@Data而不换注解,给双向关联的字段加排除注解即可:

@Entity
@Table(name = "users")
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserEntity {
    // ...其他字段
    
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
    @JoinColumn(name = "hometown_id", referencedColumnName = "id")
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    private HometownEntity hometownEntity;
    
    @ManyToMany
    @JoinTable(
            name = "users_hobbies",
            joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "hobby_and_interest_id", referencedColumnName = "id"))
    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    private Set<HobbyAndInterestEntity> hobbyAndInterestEntities;
}

对应的HometownEntity和HobbyAndInterestEntity里的反向关联字段,也要添加同样的@EqualsAndHashCode.Exclude和@ToString.Exclude注解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:55:24