为了账号安全,请及时绑定邮箱和手机立即绑定

保存 OneToMany 关系时总是获得无限递归

保存 OneToMany 关系时总是获得无限递归

慕的地6264312 2023-07-28 15:12:08
我正在使用 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());        }    }当我尝试保存房产销售时,有人可以告诉我哪里做错了吗?非常感谢。
查看完整描述

2 回答

?
婷婷同学_

TA贡献1844条经验 获得超8个赞

简短回答

为 的字段添加@EqualsAndHashCode.Exclude注释。propertyPropertySale

长答案

发生这种情况是因为:

  1. Hibernate 使用的默认实现是,它SetHashSet基于其元素的哈希码来存储它们,并且...

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

为了解决这个问题,您有一些可用的选项:

  • 替换@Data@Getter@Setteron class Property。由于它不用作 a 内的元素Set,因此它可能 不需要覆盖hashCode/equals,这与PropertySale.

  • 在字段上添加@EqualsAndHashCode.Exclude(and ) ,因此不会调用。@ToString.ExcludePropertySale.propertyPropertySale.hashCodeProperty.hashCode

  • 编写您自己的hashCode/equals实现PropertySale(在这种情况下,Lombok 不会生成它们)而无需调用(例如,Property.hashCode您仍然可以使用)。Property.id

奖金

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

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


查看完整回答
反对 回复 2023-07-28
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

快速解决:

更改您的 hashCode 以排除 propertySale。

我在 OneToMany 中遇到了同样的问题;然后意识到 HashCode 正在无限循环。

您只需要更改 hashCode 方法将其排除,即可解决您的问题。


查看完整回答
反对 回复 2023-07-28
  • 2 回答
  • 0 关注
  • 80 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信