猿问

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

我正在使用 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());

        }

    }


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


慕的地6264312
浏览 135回答 2
2回答

婷婷同学_

简短回答为 的字段添加@EqualsAndHashCode.Exclude注释。propertyPropertySale长答案发生这种情况是因为:Hibernate 使用的默认实现是,它SetHashSet基于其元素的哈希码来存储它们,并且...由于您使用的是 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在运行应用程序时这些方法都不会抛出异常。

摇曳的蔷薇

快速解决:更改您的 hashCode 以排除 propertySale。我在 OneToMany 中遇到了同样的问题;然后意识到 HashCode 正在无限循环。您只需要更改 hashCode 方法将其排除,即可解决您的问题。
随时随地看视频慕课网APP

相关分类

Java
我要回答