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

JPA一对一关联查询触发StackOverflowError问题求助

解决方案

1. 解决Jackson循环引用导致的StackOverflowError

错误栈显示问题出在Jackson序列化阶段,Person和Address互相引用,序列化时会无限递归,最终触发栈溢出。可通过以下两种方式修复:

方案一:用@JsonIgnore忽略反向引用

在Address类的person字段上添加@JsonIgnore,阻止Jackson序列化该字段,避免递归:

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Address implements Serializable {
    // ... 其他字段
    
    @JsonIgnore // 添加此注解
    @MapsId
    @OneToOne(fetch = FetchType.EAGER)
    private Person person;

    // 修正构造函数名拼写错误(Adres → Address)
    public Address(String street, String alley, String district, Person person) {
        this.street = street;
        this.alley = alley;
        this.district = district;
        this.person = person; 
    }
}

方案二:用@JsonManagedReference和@JsonBackReference区分关联层级

在主实体(Person)的关联字段加@JsonManagedReference,从实体(Address)的关联字段加@JsonBackReference,明确序列化逻辑:

// Person.java
@Entity
@Getter
@Setter
@RequiredArgsConstructor
public class Person implements Serializable { // 修正类名:Personal → Person
    // ... 其他字段
    
    @JsonManagedReference // 添加此注解
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "person")
    private Address address;
}
// Address.java
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class Address implements Serializable {
    // ... 其他字段
    
    @JsonBackReference // 添加此注解
    @MapsId
    @OneToOne(fetch = FetchType.EAGER)
    private Person person;
}

2. 修复JPA一对一关联的配置错误

当前配置存在两处关键逻辑错误:

错误1:Address主键生成策略冲突

Address使用@MapsId表示主键与Person共享,因此不能再给Address的id字段添加@GeneratedValue,否则会导致主键生成逻辑冲突:

// Address.java
@Id
// 移除@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

错误2:类名与实例化不一致

实体类定义为Personal,但保存代码中实例化的是Person,需保持类名一致:

// 将实体类名从Personal改为Person,或保存代码中改为Personal
@Entity
@Getter
@Setter
@RequiredArgsConstructor
public class Person implements Serializable {
    // ... 原有字段不变
}

3. 清理冗余代码

保存代码中的p1.setId(p1.getId());是冗余操作(Person的id为自增主键,无需手动设置),直接删除:

public String createUser(){
    Person p1 = new Person();
    // 移除该行:p1.setId(p1.getId());
    p1.setPersonName("testPerson");
    p1.setPersonLastName("testPerson");
    p1.setAddress(new Address("test","test","test",p1));
    personRepository.save(p1);
    return "Save is successful";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 11:45:33