我正在使用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;
...
我这样保存财产出售:
@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)
...
当我尝试保存房地产时,有人可以告诉我我做错了什么吗?非常感谢。
答案 0 :(得分:1)
在property
的字段PropertySale
中添加@EqualsAndHashCode.Exclude
注释。
发生这种情况是因为:
default implementation of Set
used by Hibernate is HashSet
(基于其元素的哈希码来存储它们),以及...
由于使用的是Lombok的@Data
批注,因此哈希码(以及equals和toString)实现将所有类字段都考虑在内。这意味着Property.hashCode()
会调用PropertySale.hashCode()
,反之亦然,这会导致您每次调用它们中的任何一个时都会遇到堆栈溢出错误(如果您调用.equals()
或.toString()
和这两个类别中的任何一个。
为解决此问题,您可以使用一些选项:
@Data
上用@Getter
和@Setter
替换Property
。由于它不用作Set
内的元素,因此与PropertySale
不同,它可能 doesn't need to override hashCode
/equals
。@EqualsAndHashCode.Exclude
上添加@ToString.Exclude
(和PropertySale.property
),因此PropertySale.hashCode
将不会调用Property.hashCode
。hashCode
的情况下为equals
编写自己的PropertySale
/ Property.hashCode
实现(在这种情况下Lombok不会生成它们)(您仍然可以使用{{1 }},例如。正如我提到的,Property.id
可能会出现相同的问题,但是更正与toString
/ equals
相同:ToString.Exclude
/避免使用{{1} } /自定义实现...
您还可以编写单元测试,以确保在运行应用程序时这些方法均不会抛出hashCode
。