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
相关产品推荐
相关产品推荐

