2014-02-22 121 views
2

我試圖在數據庫中堅持多對一的關係時被卡住了。我的方法對我來說似乎是邏輯的,但休眠打我的臉與java.lang.StackOverflowError。讓我說明起始情況:Hibernate:java.lang.StackOverflowError嘗試持久化對象圖時

Relationship of Account and Person

帳戶和人員記錄已經在DATABSE堅持,但是帳號和人還是要通過像account.setPerson(person);我嘗試下面的代碼語句連接在一起。讓我一步一步向您介紹代碼。

打開會話:

Session session = sessionFactory.openSession(); 
session.beginTransaction(); 

查詢所有賬戶用to_attribute。此屬性用於與名爲from_attribute的人員進行鏈接。這些屬性是從xml配置文件中提取的,並作爲定義外鍵關係的基礎。

List<Account> queried_accounts = HibernateUtils.queryList(
        session.createQuery("" 
          + "select distinct acc from Account as acc" 
          + " inner join acc.accountAttributes as accAtt" 
          + " inner join accAtt.aa_pk.attribut as attr" 
          + " where attr.name='" + to_attribute + "'") 
      ); 

查詢所有人員

List<Person> queried_persons = HibernateUtils.queryList(session.createQuery("from Person")); 

鏈接與匹配的人的所有帳戶在一起。一個人匹配,如果他的from_attribute中的值等於to_attribute的值。 我想這段代碼會導致一個StackOverflow,但我不知道爲什麼。首先,我認爲它的原因是,許多對象在session.getTransaction().commit()之前被改變。但即使session.flush()沒有做到這一點。 我知道,這個代碼不是很聰明。它會導致「帳戶數量記錄」x「人員記錄數量」讀取操作加上相同數量的相同檢查。所以,它的運行時複雜度爲O(n^2)。如我錯了請糾正我。

for (Account account : queried_accounts) { 
       String account_to_attribut_wert = account.getAttributeValue(to_attribute); 
       for (Person person : queried_persons) { 
        if (person.getAttributeValue(from_attribute).equals(account_to_attribut_wert)) { 
         account.setPerson(person); 
         // session.flush(); 
        } 
       } 

      } 

session.getTransaction().commit(); 
session.close(); 

那麼,你能幫我解決嗎?我不知道如何避免StackOverflowError這是堆棧跟蹤(此跟蹤很長,但始終包含相同的文本)。

在 org.hibernate.internal.SessionImpl.getLoadQueryInfluencers(SessionImpl.java:2071) 在 org.hibernate.engine.spi.QueryParameters.processFilters(QueryParameters.java:481)java.lang.StackOverflowError的 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:188) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:137) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.execute負載(AbstractLoadPlanBasedLoader.java:102) 在 org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186) 在 org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java: 4120) 在 org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502) 在 org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467) 在 org.hibernate作爲.event.internal.DefaultLoadEventListener。負載(DefaultLoadEventListener.java:212) 在 org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274) 在 org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150) 在org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1066) 在 org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:985) 在 org.hibernate.type.EntityType.resolveIdentifier( EntityType.java:673) 在org.hibernate.type.EntityType.resolve(EntityType.java:489)在 org.hibernate.type.ComponentType.resolve(ComponentType.java:668)在 org.hibernate.loade r.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:158) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:148) 在 org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:97) at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails $ EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:255 ) 在 org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(文摘actLoadPlanBasedLoader.java:138) 在 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102) 在 org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader。的java:186) 在 org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4120) 在 org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502) 在 有機.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467) at org.hibernate.event.intern al.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212) 在 org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274) 在 org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener。的java:150) 在org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1066) 在 org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:985) 在 org.hibernate.type。 EntityType.resolveIdentifier(EntityType.java:673) at org.hibernate.type.EntityType.resolve(EntityType.java:489)at org.hibernate.type.ComponentType.resolve(ComponentType.java:668)

回答

0

我相信只有導致這種情況的原因可能是遞歸調用。 您應該嘗試刪除這些遞歸調用,但對於您的問題,嘗試將查詢的flush模式設置爲FlushModeType.COMMIT。

由於這是由於StackOverflow引起的,如果您必須使用遞歸調用,您也可以使用Xss JVM選項增加堆棧大小。

+0

嗨@wonhee,是的,一個遞歸調用,StackOverfloeError的最常見的原因,但我找不到,resp。沒有線索,在那裏我遞歸遞歸。我在哪裏可以設置我的FlushModeType?在會話對象?也許,增加堆棧大小是一種選擇,但我認爲問題不是太小。現在,當我執行兩個UnitTests時,即使是一個StackOverfloeError,也只是在Person表中寫入一個讀取的記錄,但只有在兩次執行相同的測試時纔會發生。非常隱晦...... –

+0

我相信你可以在創建Session實例後執行setFlushMode(FlushMode.COMMIT)。如果你什麼都沒做,默認是AUTO。 – wonhee