Hibernate OneToMany java.lang.StackOverflower错误
这是我在堆栈上的第一个问题,所以请温柔一点:D 我正试图建立一对一的关系。当我试图从数据库中获取一些数据时,我得到了StackOverflowerError。但当我去掉一个零件时,一切正常。这是我的REST服务的一部分,目前它运行在VMware vFabric服务器和MySQL数据库上 获取示例: MySQL脚本: 课程: 编辑:Hibernate OneToMany java.lang.StackOverflower错误,java,hibernate,stack-overflow,one-to-many,Java,Hibernate,Stack Overflow,One To Many,这是我在堆栈上的第一个问题,所以请温柔一点:D 我正试图建立一对一的关系。当我试图从数据库中获取一些数据时,我得到了StackOverflowerError。但当我去掉一个零件时,一切正常。这是我的REST服务的一部分,目前它运行在VMware vFabric服务器和MySQL数据库上 获取示例: MySQL脚本: 课程: 编辑: @JsonManagedReference @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER) Se
@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
多亏了@Thihara和@KarIP,我才能够解决这个问题。我为球队和联赛超越了toString(),如下所示:
@Override
public String toString() {
return "League [id=" + id + ", name=" + name + "]";
}
@Override
public String toString() {
return "Team [id=" + id + ", name=" + name + "]";
}
并且能够根据需要从数据库中获取数据。但在解析时,我得到了无限循环的JAXB错误。所以我用@xmlacessortype(xmlacesstype.FIELD)
注释了Team和League类,所以它不会将方法和TeamLeague
字段看作@xmltransive
,所以它不会被解析
在这里,我甚至可以删除我的toString()实现,它仍然可以工作。
我不完全清楚为什么。
问题解决了,但我想听听更精确的解释。我不知道为什么JAXB停止了数据获取,即使是在整个DB通信过程之后(或者不是?)。
更具体地说,我用运动衫:
@GET
@Path("search/id")
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public List<League> searchById(@QueryParam("id") int id) {
return Arrays.asList(leagueDAO.getById(id));
}
@GET
@路径(“搜索/id”)
@产生({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
公共列表searchById(@QueryParam(“id”)int-id){
返回Arrays.asList(leagueDAO.getById(id));
}
它抛出StackOverFlow的唯一方法是递归访问您球队的联赛
一队对一队对一队
我猜有一个函数试图将对象反射或递归地转换为其他表示形式,从而产生一个无限循环。我遇到了一个非常类似的问题。我在模型对象上使用Lombok的
@Data
注释来自动生成getter、setter和其他标准方法。我相信Lombok生成的toString()
方法在我的团队
和联盟
对象之间引入了循环依赖关系。当我试图从我的League
对象中获取Set teams
时,我得到了一个java.lang.StackOverflowerError
,因为Spring调用toString方法是为了记录日志
我通过去掉Lombok的
toString()
方法解决了这个问题。我用Lombok的@Getter
和@Setter
注释替换了@Data
注释。这样,我仍然可以从免费的getter和setter中获益,而不必使用toString()
方法 我也有类似的问题,对我来说,这一切都无济于事
有助于这一方法:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "order_id")
@Fetch(value = FetchMode.SUBSELECT)
private List<Product> orderLines;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name=“订单号”)
@Fetch(值=FetchMode.SUBSELECT)
私有列表命令行;
name=“order\u id”是产品表中的外键列
而且我没有在产品实体中添加任何内容。循环依赖关系可以源于Lombok的
toString()
自动生成方法,如果您使用@Data
复杂注释。要排除某个字段的循环相关性,请执行以下操作:
@Entity
@Data
public class Team {
...
@ToString.Exclude
@ManyToOne
private League league;
}
对我来说,Lombok提供的hashCode和toString默认实现都导致了这个问题 可以使用此批注排除equalsAndHasCode和单个批注的成员:
@EqualsAndHashCode(exclude = {"certificates", "payment"})
另外,如果您只想从equals方法中排除成员,Lombok提供:@ToString.exclude
@ToString.Exclude
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "shipment")
private Set<Certificate> certificates;
@ToString.Exclude
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy=“shipping”)
专用集证书;
我犯了这个错误,因为我正在使用jackson解析映射到json两侧的对象列表,这导致了一个无限循环
如果您处于相同的情况,您可以通过使用@JsonManagedReference
和@JsonBackReference
注释来解决此问题
API中的定义:
- JsonManagedReference(): 注释用于指示带注释的特性是双向特性的一部分 领域之间的联系;其角色是“家长”(或“前进”) 链接属性的值类型(类)必须有一个兼容的 用JsonBackReference注释的属性。联动是这样处理的 使用此注释注释的属性是否正常处理 (正常序列化,反序列化无特殊处理);它是 需要特殊处理的匹配返回引用
- JsonBackReference:(): 用于指示关联属性是的一部分的注释 字段之间的双向链接;其角色是“儿童”(或 “后退”)链接。属性的值类型必须是bean:不能是 集合、映射、数组或枚举。联动装置的处理应确保 使用此批注批注的属性未序列化;和 在反序列化过程中,其值设置为具有 “托管”(前向)链接
@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
另一个解决方案是使用
@JsonIgnore
,它只会将字段设置为null。我用Lombok的@Getter和@Setter注释替换了@Data注释。当我遇到这个问题时,我正在将实体转换为dto。然后我意识到我调用的是用one注释的父类,而不是用manytone注释的桥类。因为父级已经调用了网桥,所以它变成了循环的,并且集合递归。我没有调用填充的父方法,而是初始化并填充子对象中的父对象。另请参见:
在我的例子中,我在一个实体上使用了@IdClass
注释,该实体的主键中包含一个外键:
@IdClass(MyEntity.MyEntityKey.class)
public class MyEntity {
public static class MyEntityKey {
private Foo parent;
private int count;
// Getters, setters, constructor, ...
}
@Id
private Foo parent;
@Id
private int number;
//...
}
现在,当加载Foo
并急切地加载所有MyEntity
s时,Hibernate又被激活了
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
@IdClass(MyEntity.MyEntityKey.class)
public class MyEntity {
public static class MyEntityKey {
private Foo parent;
private int count;
// Getters, setters, constructor, ...
}
@Id
private Foo parent;
@Id
private int number;
//...
}
public class ProductEntity implements Serializable {
private List<ProductPriceEntity> refProductPriceEntities = new ArrayList<>();
@OneToMany(
mappedBy = "product",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
orphanRemoval = true,
targetEntity = ProductPriceEntity.class)
@JsonIgnoreProperties(value = "product", allowSetters = true)
public List<ProductPriceEntity> getRefProductPriceEntities() {
return refProductPriceEntities;
}
public void setRefProductPriceEntities(List<ProductPriceEntity> refProductPriceEntities) {
this.refProductPriceEntities = refProductPriceEntities;
}
}
public class ProductPriceEntity {
private ProductEntity product;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false),
@JoinColumn(name = "product_version_id", referencedColumnName = "version_id", nullable = false)
})
@JsonIgnoreProperties(value = "refProductPriceEntities", allowSetters = true)
public ProductEntity getProduct() {
return product;
}
public void setProduct(ProductEntity product) {
this.product = product;
}
}
Class A(Details.class)-
@OneToOne
@JoinColumn(name="billing_address_id")
private Address billingAddress;
@OneToOne
@JoinColumn(name="shipping_address_id")
private Address shippingAddress;
Class B(Address.class)-
@OneToOne(mappedBy="billingAddress")
private Details billingDetails;
@OneToOne(mappedBy="shippingAddress")
private Details shippingDetails;
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Team {
...