java - Hibernate:尝试保留对象图时出现 java.lang.StackOverflowError

标签 java hibernate stack-overflow

我在尝试在数据库中保持多对一关系时遇到困难。我的方法对我来说似乎是合乎逻辑的,但是 hibernate 以 java.lang.StackOverflowError 打我的脸。让我来说明一下起始情况:

Relationship of Account and Person

Account 和 Person 记录已经保存在数据库中,但是 Account 和 Person 仍然必须通过 account.setPerson(person); 之类的语句链接在一起 我尝试了以下代码。让我逐步向您介绍代码。

打开 session :

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 中的值等于 account 中的 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

这是堆栈跟踪(此跟踪很长,但始终包含相同的文本)。

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

最佳答案

我相信造成这种情况的唯一原因可能是递归调用。 您绝对应该尝试删除那些递归调用,但对于您的问题,请尝试将查询的刷新模式设置为 FlushModeType.COMMIT。

由于是 StackOverflow 的缘故,如果无论如何都必须使用该递归调用,您也可以使用 Xss JVM 选项增加堆栈大小。

关于java - Hibernate:尝试保留对象图时出现 java.lang.StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21954314/

相关文章:

java - 需要从 JFrame 中的单选按钮获取输入,并在另一个类中使用选定的输入

java - 迭代集合时的数据累积设计

Spring Hibernate - 无法为当前线程获取事务同步 session

即使不存在递归函数,JavaScript 堆栈也会溢出

java - 如何部分模拟 java.lang.String 的 'equalsIgnoreCase' 方法

java - 为什么允许使用子类的构造函数实例化父类对象?

java - JPA Hibernate::实体的继承,带有附加的 OneToMany 列表

java - 节点 : org. hibernate.hql.internal.ast.tree.IdentNode HQL 没有数据类型

c++ - C++ 标准对堆栈溢出有何规定?

Java同时调用类