![](/img/trans.png)
[英]How to persist self-referencing entity using two tables in Hibernate?
[英]self-referencing entity in hibernate causes StackOverflowErrors
在我的一個Java實體(MyState)中,我引用了它自己。 批注如下所示:
@OneToOne
@JoinColumn(name = "previousStateId", nullable = true,
foreignKey = @ForeignKey(name = "fk_state_previousstate"))
private MyState previousState;
過去,這種方法一直工作良好,直到表增長並且越來越多的狀態指向彼此為止。 現在,當我嘗試獲取最新的MyState時,由於嵌套太深而發生StackOverflowError。 有什么比這里更好的網站問我的問題? ;-)
我最終需要訪問根狀態(一長串狀態中的第一個狀態),還需要訪問前一個狀態。
有什么方法可以避免獲取所有參考? 我試圖添加一個指向原始狀態的新字段“ rootState”。 當然,這是2個狀態的短鏈,因此效果很好。
但是,我確實也需要以前的狀態。 我是否應該嘗試通過將previousState的previousState設置為null來手動斷開鏈,還是有更好的選擇?
-編輯
我檢查以確保彼此指向的狀態中沒有周期,沒有周期。
部分堆棧跟蹤:
Caused by: java.lang.StackOverflowError
at com.mchange.v2.c3p0.impl.NewPooledConnection.handleThrowable(NewPooledConnection.java:492)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.getWarnings(NewProxyPreparedStatement.java:1045)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.handleAndClearWarnings(SqlExceptionHelper.java:317)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logAndClearWarnings(SqlExceptionHelper.java:273)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.close(JdbcCoordinatorImpl.java:529)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.release(JdbcCoordinatorImpl.java:421)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:160)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:258)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1070)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:989)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:716)
at org.hibernate.type.EntityType.resolve(EntityType.java:502)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:170)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:144)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(AbstractRowReader.java:244)
at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:215)
at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:140)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)
at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4126)
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502)
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:258)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)
.... and on and on and on....
除非您具有循環依賴性,否則這應該起作用。 由於存在循環依賴性,因此可能會發生StackOverflowError,這是因為無限循環遞歸地獲取了先前的狀態。
例如,當您有兩個實體A和B。A指向B,B指向A時,您將遇到無限循環,並且使用EAGER提取策略,您將得到StackOverflowError。
您需要檢查數據庫中是否沒有任何循環依賴性。
顯然這是一個錯誤。 如果您有一個實體Person,並且該實體具有對另一個Person的嵌套引用,則意味着嵌套的Person具有另一個嵌套鏈接,因此它也嵌套了子嵌套,依此類推。 您不必引用帶有Person對象的嵌套Person。 改用唯一的ID。
public class Person{
private int idNestedPerson;
//fields + getters/setters
}
現在您有2個選擇:使用外鍵或將其保持不變。 如果選擇第一個選項,則必須映射該nestedId,但我建議您開始使用第二個選項。 這樣,您就可以擁有一個具有引用“父親”人物的ID的人物。 如果該nestedId為!= null或> 0(根據您為ID分配的類型),則表示該人是嵌套的;相反,如果未填充該ID或該ID的默認int值為0,則表示該人是“根”,因此不嵌套。 請參閱“分層數據”以獲取更多詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.