gpt4 book ai didi

java - 保存 OneToMany 关系时总是获得无限递归(已使用 @JsonBackReference 和 @JsonManagedReference)

转载 作者:行者123 更新时间:2023-12-02 09:31:26 28 4
gpt4 key购买 nike

我正在使用 Spring Boot 编写 OneToMany 关系,一个属性可以有多个 propertySale。

这是我的属性类:

@Data
@Getter
@Entity
@Table(name = "Property")
public class Property {
@Id
@GeneratedValue
private Long id;

@OneToMany(mappedBy="property", cascade = CascadeType.ALL, targetEntity = PropertySale.class)
@JsonManagedReference
private Set<PropertySale> propertySales;
...

这是我的 propertySale 类:

@Data
@Getter
@Entity
@Table(name = "PropertySale")
public class PropertySale {
@Id
@GeneratedValue
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "property_id", referencedColumnName = "id")
@JsonBackReference
private Property property;
...

我像这样保存 propertySale:

@Override
public ResponseEntity<PropertySale> savePropertySale(PropertySale propertySale) {
Optional<Property> existPropertyOpt = this.propertyRepository.findById(propertySale.getProperty().getId());

if(existPropertyOpt.isPresent()){
Example<PropertySale> propertySaleExample = Example.of(propertySale);
Optional<PropertySale> existPropSale = this.propertySaleRepository.findOne(propertySaleExample);
if(existPropSale.isPresent()){
throw new PropertySaleAlreadyExistException();

}else{
Property existProperty = existPropertyOpt.get();
propertySale.setProperty(existProperty);
existProperty.addPropertySale(propertySale);
this.propertyRepository.save(existProperty);
return new ResponseEntity<>(propertySale, HttpStatus.CREATED);
}

}else{
throw new PropertyNotFoundException(propertySale.getProperty().getId());
}
}

我明白

Caused by: java.lang.StackOverflowError
at java.util.AbstractSet.hashCode(AbstractSet.java:122)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:459)
at com.mikason.PropView.dataaccess.estateEntity.Property.hashCode(Property.java:12)
at com.mikason.PropView.dataaccess.commercialEntity.PropertySale.hashCode(PropertySale.java:10)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:459)
at com.mikason.PropView.dataaccess.estateEntity.Property.hashCode(Property.java:12)
at com.mikason.PropView.dataaccess.commercialEntity.PropertySale.hashCode(PropertySale.java:10)
at java.util.AbstractSet.hashCode(AbstractSet.java:126)
...

当我尝试保存特性销售时,有人可以告诉我哪里做错了吗?非常感谢。

最佳答案

简短回答

PropertySale的字段property中添加@EqualsAndHashCode.Exclude注释。

长答案

发生这种情况是因为:

  1. default implementation of Set used by Hibernate is HashSet,它基于其元素的哈希码来存储它们,并且...

  2. 由于您使用的是 Lombok 的 @Data 注释,因此哈希码(以及 equals 和 toString)实现会考虑所有类字段。这意味着 Property.hashCode() 调用 PropertySale.hashCode() ,反之亦然,导致每当调用其中任何一个时都会出现堆栈溢出错误(这如果您使用这两个类中的任何一个调用 .equals().toString() ,也会发生这种情况。

为了解决此问题,您可以使用一些选项:

  • Property 类中的 @Data 替换为 @Getter@Setter。由于它不用作 Set 内的元素,因此它可能 doesn't need to override hashCode/equals ,与 PropertySale 不同。
  • 在字段 PropertySale.property 上添加 @EqualsAndHashCode.Exclude(和 @ToString.Exclude),因此 PropertySale.hashCode 不会调用 Property.hashCode
  • PropertySale 编写您自己的 hashCode/equals 实现(在这种情况下,Lombok 不会生成它们),而无需调用 Property .hashCode(例如,您仍然可以使用 Property.id)。

奖金

正如我提到的,toString 可能会出现同样的问题,但修正方法与 equals/hashCode 几乎相同:ToString.Exclude/避免@Data/自定义实现...

您还可以编写单元测试,以确保在运行应用程序时这些方法都不会抛出 StackOverflowError

关于java - 保存 OneToMany 关系时总是获得无限递归(已使用 @JsonBackReference 和 @JsonManagedReference),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57932048/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com