[英]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.