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

Spring中@OneToMany关联异常:无法为同一所有者添加多只宠物

Spring 一对多关联问题:无法为同一所有者添加多只宠物

问题概述

配置所有者(Owners)与宠物(Pets)的一对多关联时,出现无法为同一所有者添加多只宠物的异常:添加第一只宠物正常,但添加第二只时,宠物会被错误关联到其他所有者,原所有者的宠物列表无变化。

相关实体类代码

Owners 实体类

@Entity
@Table(name="owners_table")
public class Owners {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    
    @Column(nullable=false)
    private String name;
    
    @Column(nullable=false)
    private String phoneNumber;
    
    @Column(nullable=true)
    private String email;
    
    @Column(nullable=false)
    private String address;
     
    @OneToMany(fetch=FetchType.LAZY,mappedBy="id")
    @JsonManagedReference(value="pet-owners")
    @JsonIgnore
    private List<Pets> pets;

    
    public Owners() {
        
    }
    @JsonCreator
    public Owners(Integer id, String name, String phoneNumber, String email, String address) {
        this.id = id;
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.email = email;
        this.address = address;
    }
    
    // 省略getter和setter方法
}

Pets 实体类

@Entity
@Table(name="pets_table")
public class Pets {
    private String name;
    private String breed;
    private Date birthDate;
    
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonBackReference(value="pet-owners")
    @JoinColumn(name = "owner_id")
    private Owners owner;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    
    
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name="walk_id")
    @JsonBackReference(value="pet-walks")
    private DogWalking walk;
    

    public Pets() {
    }
    
    @JsonCreator
    public Pets(String name, String breed, Date birthDate,  Owners owner , Integer id) {
        this.name = name;
        this.breed = breed;
        this.birthDate = birthDate;
        this.id = id;
    }
    
    // 省略getter和setter方法
}

问题现象

  • 查询id为6的所有者,初始宠物列表为空:
    请求:localhost:8080/owners/6
    返回结果:

    {
            "id": 6,
            "name": "Lucas Calado",
            "phoneNumber": "(83) 98326-9273",
            "email": "lucasthecalado@gmail.com",
            "address": "Rua Bancário João Luiz , 92",
            "pets": []
    }
    
  • 为该所有者添加第一只宠物,操作成功:
    请求:localhost:8080/pets/insert
    请求体:

    {
            "name": "Fenrir",
            "breed": "Husky siberiano",
            "birthDate": "2017-03-08T03:00:00.000+00:00",
            "owner":{
                "id":6
            },
            "walks": null
    }
    

    再次查询id为6的所有者,宠物列表包含该宠物:

    {
            "id": 6,
            "name": "Lucas Calado",
            "phoneNumber": "(83) 98326-9273",
            "email": "lucasthecalado@gmail.com",
            "address": "Rua Bancário João Luiz , 92",
            "pets": [
                {
                    "name": "Fenrir",
                    "breed": "Husky siberiano",
                    "birthDate": "2017-03-08T03:00:00.000+00:00",
                    "id": 6,
                    "walks": null
                }
            ]
        }
    
  • 尝试为同一所有者添加第二只宠物时,该宠物被错误关联到id为7的所有者,id为6的所有者宠物列表无变化:
    请求:localhost:8080/pets/insert
    请求体:

    {
        "name": "Roabson",
        "breed": "Pug",
        "birthDate": "2018-12-02T03:00:00.000+00:00",
        "owner":{
            "id":6
        }
    }
    

解决方案

1. 修正@OneToMany的mappedBy属性

Owners类中@OneToMany注解的mappedBy参数值错误,应指向Pets类中关联Owners的属性名owner,而非id。修改后代码:

@OneToMany(fetch=FetchType.LAZY,mappedBy="owner")
@JsonManagedReference(value="pet-owners")
@JsonIgnore
private List<Pets> pets;

mappedBy用于指定双向关联中被动方(多的一方)的关联属性,这里Pets类用private Owners owner;关联所有者,必须设为owner才能正确建立关联。

2. 优化宠物添加的业务逻辑

添加宠物时,需从数据库获取持久化状态的Owners对象,而非仅用id构造临时对象。示例代码:

public Pets insertPet(Pets pet) {
    // 查询数据库获取持久化的所有者对象
    Owners owner = ownerRepository.findById(pet.getOwner().getId())
            .orElseThrow(() -> new RuntimeException("所有者不存在"));
    pet.setOwner(owner);
    // 维护双向关联一致性:将宠物添加到所有者的宠物列表
    owner.getPets().add(pet);
    ownerRepository.save(owner);
    return petRepository.save(pet);
}

避免临时对象导致的关联异常,同时保证双向关联数据一致。

3. 修正Pets构造函数

Pets的@JsonCreator构造函数未设置owner属性,导致反序列化时无法正确关联所有者。修改后:

@JsonCreator
public Pets(String name, String breed, Date birthDate, Owners owner, Integer id) {
    this.name = name;
    this.breed = breed;
    this.birthDate = birthDate;
    this.owner = owner; // 补充设置owner属性
    this.id = id;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:55:16