[英]Hibernate OneToMany java.lang.StackOverflowError
这是我在堆栈上的第一个问题,所以请温柔:D
我正在尝试创建 hibernate OneToMany 关系。 当我尝试从我的数据库中获取一些数据时,我得到了 StackOverflowError。 但是当我删除 OneToMany 部分时,一切正常。 这是我的 REST 服务的一部分,目前它在 VMware vFabric 服务器和 MySQL DB 上运行。
获取示例:
@Inject
private EntityManager entityManager;
...
entityManager.find(League.class, 1);
...
entityManager.find(Team.class, 1);
MySQL 脚本:
CREATE TABLE league (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(20) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE team (
team_id int(11) NOT NULL AUTO_INCREMENT,
name varchar(20) COLLATE utf8_unicode_ci NOT NULL,
fk_leagueId int(11) NOT NULL,
PRIMARY KEY (team_id),
FOREIGN KEY (fk_leagueId) REFERENCES league(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
课程:
@XmlRootElement
@Entity
@Table(name = "team")
@Data
public class Team {
@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
@Column(name = "team_id")
private int id;
@Column(name = "name")
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fk_leagueId", nullable = false)
private League league;
}
@XmlRootElement
@Entity
@Table(name = "league")
@Data
public class League {
@Id
@GeneratedValue(generator = "increment")
@GenericGenerator(name = "increment", strategy = "increment")
@Column(name = "id")
private int id;
@Column(name = "name")
private String name;
//if I comment 2 lines below, there is no error, and everything works fine
@OneToMany(fetch = FetchType.LAZY, mappedBy = "league")
private Set<Team> teams;
}
错误:
Hibernate: select league0_.id as id1_1_0_, league0_.name as name2_1_0_ from league league0_ where league0_.id=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Hibernate: select teams0_.fk_leagueId as fk3_1_1_, teams0_.team_id as team1_4_1_, teams0_.team_id as team1_4_0_, teams0_.fk_leagueId as fk3_4_0_, teams0_.name as name2_4_0_ from team teams0_ where teams0_.fk_leagueId=?
Exception in thread "tomcat-http--3" java.lang.StackOverflowError
at org.jboss.logging.JDKLogger.translate(JDKLogger.java:73)
at org.jboss.logging.JDKLogger.isEnabled(JDKLogger.java:85)
at org.jboss.logging.JDKLogger.doLog(JDKLogger.java:41)
at org.jboss.logging.Logger.debug(Logger.java:406)
at org.hibernate.internal.CoreMessageLogger_$logger.debug(CoreMessageLogger_$logger.java:525)
at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:104)
at org.hibernate.engine.jdbc.spi.SqlStatementLogger.logStatement(SqlStatementLogger.java:95)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:180)
at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:159)
at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1858)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1835)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1815)
at org.hibernate.loader.Loader.doQuery(Loader.java:899)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:311)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2234)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:65)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:674)
at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1849)
at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:549)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:234)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:545)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:124)
at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:428)
at com.lukaszb.motspe.webapp.model.League.hashCode(League.java:21)
at com.lukaszb.motspe.webapp.model.Team.hashCode(Team.java:20)
at java.util.HashMap.hash(HashMap.java:351)
at java.util.HashMap.put(HashMap.java:471)
at java.util.HashSet.add(HashSet.java:217)
...
编辑:
感谢@Thihara 和@KarIP,我能够解决这个问题。 我已经为 Team 和 League 覆盖了 toString(),如下所示:
@Override
public String toString() {
return "League [id=" + id + ", name=" + name + "]";
}
@Override
public String toString() {
return "Team [id=" + id + ", name=" + name + "]";
}
并且能够根据需要从数据库中获取数据。 但是在解析时,我得到了无限循环的 JAXB 错误。 所以我用@XmlAccessorType(XmlAccessType.FIELD)
注释了 Team and League class ,所以它不会查看方法,而 Team league
字段为@XmlTransient
,所以它不会被解析。
在这里,我什至可以删除我的 toString() 实现,它仍然有效。 我不完全确定为什么。 问题已解决,但我想听听更准确的解释。 我不知道为什么 JAXB 停止数据获取,即使它是在整个数据库通信过程之后(或者不是?)。 更具体地说,我为此使用 Jersey :
@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));
}
我有一个非常相似的问题。 我在模型对象上使用 Lombok 的@Data
注释来自动生成 getter、setter 和其他标准方法。 我相信 Lombok 生成的toString()
方法在我的Team
和League
对象之间引入了循环依赖。 当我试图从我的League
对象中获取Set<teams> teams
,我得到了一个java.lang.StackOverflowError
因为 Spring 正在调用 toString 方法进行日志记录。
我通过摆脱 Lombok 的toString()
方法解决了这个问题。 我用 Lombok 的@Getter
和@Setter
注释替换了@Data
注释。 这样我仍然可以从免费的 getter 和 setter 中受益,而无需获得toString()
方法。
它可以抛出 StackOverFlow 的唯一方法是递归访问您团队的联赛......
球队对联赛球队对联赛
我猜有一些函数试图将您的对象反射或递归地转换为其他表示形式,从而导致无限循环。
如果您使用@Data
复杂注释,循环依赖可以源自Lombok 的toString()
自动生成方法。 要排除某个字段的循环依赖:
@Entity
@Data
public class Team {
...
@ToString.Exclude
@ManyToOne
private League league;
}
我遇到此错误是因为我正在使用 jackson 将映射在@OneToMany
和@ManyToOne
两侧的对象列表解析为 json,这导致了无限循环。
如果您处于相同的情况,则可以使用@JsonManagedReference
和@JsonBackReference
注释来解决此问题。
来自 API 的定义:
JsonManagedReference( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html ):
用于指示被注释的属性是字段之间双向链接的一部分的注释; 并且它的作用是“父”(或“转发”)链接。 属性的值类型(类)必须有一个用 JsonBackReference 注释的兼容属性。 链接的处理使得用这个注解注解的属性得到正常处理(正常序列化,反序列化没有特殊处理); 它是需要特殊处理的匹配反向引用
JsonBackReference:( https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html ):
用于指示关联属性是字段之间双向链接的一部分的注解; 并且它的作用是“子”(或“后”)链接。 属性的值类型必须是 bean:不能是 Collection、Map、Array 或枚举。 处理链接使得使用此注释注释的属性不会被序列化; 并且在反序列化期间,它的值被设置为具有“托管”(前向)链接的实例。
例子:
所有者.java:
@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;
汽车.java:
@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;
另一种解决方案是使用@JsonIgnore
,它只会为该字段设置 null 。
对我来说,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;
我用 Lombok 的 @Getter 和 @Setter 注释替换了 @Data 注释
我有类似的问题,在我的情况下,这没有任何帮助。
帮助了这种方法:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "order_id")
@Fetch(value = FetchMode.SUBSELECT)
private List<Product> orderLines;
name = "order_id" 是 Product 表中的外键列。
而且我没有在 Product 实体中放入任何东西。
我挣扎了很长时间,并认为这是 Kotlin 的一个问题,为什么它会抛出 Stackoverflow 异常。 最后是杰克逊,它被 Spring Hibernate 使用并导致 Stackoverflow。
您可以通过在两侧设置@JsonIgnoreProperties
来解决该问题。 例子:
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;
}
}
最后是另一边,这导致了stackoverflow异常。
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;
}
}
当我遇到这个问题时,我正在将实体转换为 dto。 然后我意识到我正在从用 manytoone 注释的桥类调用用 onetomany 注释的父类。 因为父级已经调用了桥,它变成了循环并且集合递归。 我没有调用填充的父方法,而是在子中初始化并填充父方法。
另请参阅: Hibernate 在查询时抛出 StackOverflowError
就我而言,我在一个实体上使用了@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
,Hibernate 在构建导致堆栈溢出的键时再次加载父实体Foo
。
我通过使用显式键属性(即在MyEntityKey
包含 Foo 的键,而不仅仅是对Foo
的引用)对 id 进行建模来解决该问题,如复合键处理中所示, 在 Spring boot java 中使用 @Idclass 注释(也适用于非春季休眠)。 简而言之:使用@JoinColumns
注释来指定导航属性(到父级)和 id 列之间的关系。
在休眠的 OneToOne 映射中出现此错误,实体类无法转换为字符串。
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;
错误 - 因为 A 类正在调用 B 类,类似地,B 类正在调用 A 类。需要删除两者之一。 那么这个问题就会得到解决。
当我遇到这个问题时,我可以使用@JsonManagedReference
和@JsonBackReference
解决它,但这意味着在反序列化为 json 时,只有实体的一侧有子项。 即在您的球队和联赛示例中,只有联赛会显示球队,而球队不会显示它属于哪个联赛。
要允许双方, @JsonIdentityInfo
在您的实体中使用@JsonIdentityInfo
注释并删除@JsonBackReference
和@JsonManagedReference
。 您的实体将类似于:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Team {
...
这用我正在寻找的替换了循环引用。
我发现使用 @EqualsAndHashCode(onlyExplicitlyIncluded = true) 是一个很好的起点。 在大多数情况下,对象之间的相等性应该只对特定值进行。 如果你对每个实体都使用它,它将迫使你选择你真正想要包含在平等中的内容,并且可能会阻止循环内存引用。
我在保存和刷新时使用 Lombok 遇到了类似的问题。 它在我的@EqualsAndHashCode 中,因此您可以按属性名称排除子集合:
@Data
@EqualsAndHashCode(callSuper = true, exclude = "childRowCollectionProp")
@Entity
@Table(name = "parent")
public class Parent extends BaseEntityWithId{
我在“Spring Data Rest”和 Lomboks @Data 注释的组合中遇到了同样的问题。 绝对同时使用@ToString.Exclude @EqualsAndHashCode.Exclude
我的设置:
@RepositoryRestResource(collectionResourceRel = "a", path = "a")
public interface ARepository extends JpaRepository<A, Long> {
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
@EntityListeners(AuditingEntityListener.class)
@EqualsAndHashCode(callSuper = true)
public class A extends AuditMetadata<String> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String x;
private String y;
@ToString.Exclude
@EqualsAndHashCode.Exclude
@ManyToOne
private B b;
}
@RepositoryRestResource(collectionResourceRel = "b", path = "b")
public interface BRepository extends JpaRepository<B, Long> {
}
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@Entity
@EqualsAndHashCode(callSuper = true)
public class B extends AuditMetadata<String> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String k;
private String l;
private String m;
@OneToMany(mappedBy = "b", cascade = CascadeType.ALL)
private Set<A> aList = new HashSet<>();
}
这对我来说非常有效。 谢谢尼拉杰耆那教。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.