简体   繁体   English

休眠:尝试持久化对象图时发生java.lang.StackOverflowError

[英]Hibernate: java.lang.StackOverflowError while trying to persist an object graph

I'm stuck while trying to persist a many-to-one relationship in the database. 我在尝试在数据库中保持多对一关系时遇到了麻烦。 My approach seems logic to me, but hibernate hits my face with a java.lang.StackOverflowError . 我的方法对我来说似乎是合乎逻辑的,但是休眠方式却带有java.lang.StackOverflowError Let me illustrate the starting situation: 让我说明开始的情况:

帐户与人的关系

Account and Person records have already been persisted in the databse, however Account and Person still have to be linked together through a statement like account.setPerson(person); Account和Person记录已经保留在数据库中,但是Account和Person仍必须通过诸如account.setPerson(person);类的语句链接在一起account.setPerson(person); I tried the following code. 我尝试了以下代码。 Let me introduce you into the code step by step. 让我逐步向您介绍代码。

Open a session: 开启工作阶段:

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

Query all accounts with a to_attribute. 使用to_attribute查询所有帐户。 This attribute is used to link with a source attribute in person called from_attribute. 此属性用于与名为from_attribute的人员的源属性链接。 These attributes are fetched from an xml config file and serve as a basis to define the foreign key relationship. 这些属性是从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 + "'")
            );

Query all persons 查询所有人

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

Link together all accounts with a matching person. 将所有帐户与匹配的人链接在一起。 A person matches, if the value in his from_attribute is equal to the value of the to_attribute in account. 如果某人的from_attribute中的值等于帐户中to_attribute的值,则该人匹配。 I suppose that this piece of code causes a StackOverflow, but im not sure why. 我想这段代码会导致StackOverflow,但是我不确定为什么。 First, i thought its due to the fact, that many objects are altered before session.getTransaction().commit() . 首先,我认为这是由于以下事实:在session.getTransaction().commit()之前更改了许多对象。 But even session.flush() didn't do the trick. 但是,即使session.flush()也无法解决问题。 I know, this code isnt very smart. 我知道,这段代码不是很聪明。 It causes "Amount of Account records" x "Amount of person records" read operations plus the same amount for equal checks. 这将导致“帐户记录数量” x“人员记录数量”读取操作加上相同数量的相等支票。 So, its a runtime complexity of O(n^2). 因此,其运行时复杂度为O(n ^ 2)。 Correct me, if im wrong. 如果我错了纠正我。

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();

So, can you help me out with that? 那么,您可以帮我吗? I dont know how to avoid the StackOverflowError 我不知道如何避免StackOverflowError

Here is the stack trace (this trace is long, but contains always the same text). 这是堆栈跟踪(此跟踪很长,但始终包含相同的文本)。

java.lang.StackOverflowError at org.hibernate.internal.SessionImpl.getLoadQueryInfluencers(SessionImpl.java:2071) at org.hibernate.engine.spi.QueryParameters.processFilters(QueryParameters.java:481) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:188) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:137) 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:4120) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:502) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467) a org.hibernate.loader.plan上的org.hibernate.engine.spi.QueryParameters.processFilters(QueryParameters.java:481)处的org.hibernate.internal.SessionImpl.getLoadQueryInfluencers(SessionImpl.java:2071)处的java.lang.StackOverflowError。 org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:137)在org.hibernate.loader.plan.exec.internal处的exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:188) org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)处的AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)在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) t org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1066) at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:985) at 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) at org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:158) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:148) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.readRow(AbstractRowReader.java:97 在org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274)处的org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:212)在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。在org.hibernate.type.EntityType.resolve(EntityType.java:489)在org.hibernate.type.ComponentType.resolve(ComponentType.java:668)在org.hibernate.loader.plan的resolveIdentifier(EntityType.java:673) org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.resolveEntityKey(AbstractRowReader.java:148)上的.exec.process.internal.EntityReferenceInitializerImpl.resolveEntityKey(EntityReferenceInitializerImpl.java:158)在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) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129) 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:4120) 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(DefaultLoadEvent )org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(ResultSetProcessorImpl.java:129)上的org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails $ EntityLoaderRowReader.readRow(EntityLoadQueryDetails.java:255) )在org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:138)在org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(AbstractLoadPlanBasedLoader.java:102)在org。 org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4120)处的hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(AbstractLoadPlanBasedEntityLoader.java:186)在org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(位于org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:467)的org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEvent)的DefaultLoadEventListener.java:502) Listener.java:212) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1066) at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:985) at 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) org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:274)的Listener.java:212)org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:150)的org.hibernate.internal org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:985)的.SessionImpl.fireLoad(SessionImpl.java:1066)org.hibernate的org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:673)的。 org.hibernate.type.ComponentType.resolve(ComponentType.java:668)处的type.EntityType.resolve(EntityType.java:489)

I believe only reason that cause this might be recursive call. 我相信导致此问题的唯一原因可能是递归调用。 You should definitely try to remove those recursive call, but for your question try to set your query's flush mode to FlushModeType.COMMIT. 您绝对应该尝试删除这些递归调用,但是对于您的问题,请尝试将查询的刷新模式设置为FlushModeType.COMMIT。

Since it's due to StackOverflow, you might also able to increase stack size with Xss JVM option if you have to use that recursive call anyway. 由于这是由于StackOverflow引起的,因此如果您仍然必须使用该递归调用,则还可以使用Xss JVM选项来增加堆栈大小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM