问题:在用OneToMany保存一对多的数据时,报堆栈信息异常Handler dispatch failed; nested exception is java.lang.StackOverflowError。点击报错的行,竟然定位到类上的@Data注解。
解决方法:
- 把@data注解替换成@Getter、@Setter和@ToString;
并且去掉@EqualsAndHashCode或者自定义equals(Object other) 和 hashCode()方法,比如有些类只需要判断主键id是否相等即足矣。 - 用@Data注解并再加上@EqualsAndHashCode(callSuper = false, exclude={"giftSetList"}),排除掉相互引用的属性即可。
原因:
我这面报错的原因是交叉引用了,在A entity中OneToMany引用多个B entity
在B entity中ManyToOne映射了一个A entity,具体逻辑可以看下面的代码。
这里面牵涉到两个点:
-
@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集。
所以在报错行指向@Data注解,因为交叉引用,@EqualsAndHashCode循环引用就会报堆栈异常。 -
@EqualsAndHashCode 这个注解标在子类上
a. callSuper = true,根据子类自身的字段值和从父类继承的字段值来生成hashcode,当两个子类对象比较时,只有子类对象的本身的字段值和继承父类的字段值都相同,equals方法的返回值是true。
b. callSuper = false,根据子类自身的字段值 来生成hashcode, 当两个子类对象比较时,只有子类对象的本身的字段值相同,父类字段值可以不同,equals方法的返回值是true。
调整后的代码:
PostgreSQLGiftSetTagEntity和PostgreSQLGiftSetEntity的关系是一对多。PostgreSQLGiftSetTagEntity中的@OneToMany下面对应的是多个PostgreSQLGiftSetEntity;同时PostgreSQLGiftSetEntity中的@ManyToOne下对应的是一个PostgreSQLGiftSetTagEntity。
这两个entity交叉引用,如果用@EqualsAndHashCode注解无论是ture还是false都会出现java.lang.StackOverflowError。
使用@EqualsAndHashCode(callSuper = false, exclude={"giftSetList"})注解的意思就是把交叉引用的部分去掉。
@Data
@Builder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false, exclude={"giftSetList"})
@AllArgsConstructor
@Entity
@Table(name = "gift_set_tag")
public class PostgreSQLGiftSetTagEntity extends PostgreSQLUnpartitionedEntity implements GiftSetTag {
@Column(name = "image", nullable = false)
private String image;
@Column(name = "name", nullable = false)
private String name;
@OneToMany(targetEntity = PostgreSQLGiftSetEntity.class, fetch = FetchType.EAGER, mappedBy = "giftSetTag",orphanRemoval = true)
@Fetch(FetchMode.SUBSELECT)
@Cascade(CascadeType.ALL)
@OrderBy(clause = "displayOrder")
private Set<PostgreSQLGiftSetEntity> giftSetList;
}
@Data
@Builder
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false, exclude={"giftSetTag"})
@AllArgsConstructor
@Entity
@Table(name = "gift_set")
public class PostgreSQLGiftSetEntity extends PostgreSQLUnpartitionedEntity implements GiftSet {
@Column(name = "sku_ids", nullable = false)
private String skuIds;
@Column(name = "tag_id", insertable=false, updatable=false)
private String tagId;
@Column(name = "image", nullable = false)
private String image;
@Column(name = "thumbnail_image", nullable = false)
private String thumbnailImage;
@Column(name = "description")
private String description;
@Column(name = "display_order")
private Integer displayOrder;
@Column(name = "engrave_skus")
@Convert(converter = EngraveSkusConverter.class)
private Set<String> engraveSkus;
@JoinColumn(name="tag_id")
@ManyToOne(targetEntity=PostgreSQLGiftSetTagEntity.class)
private PostgreSQLGiftSetTagEntity giftSetTag;
}
参考链接:
https://blog.csdn.net/dj1955/article/details/123822789
https://www.656463.com/wenda/jiazaiguanxishiduizhanyichu_363
https://blog.csdn.net/m0_57037182/article/details/124704408
https://blog.csdn.net/c851204293/article/details/96989512
https://www.jianshu.com/p/d318ba2e84da
网友评论