Grails:双向一到一定程度地导致无尽的递归(stackoverflow)



我最近接管了另一个人的圣杯项目。

我正在使用Grails 3.2.11和Hibernate 4.3.10

我正在添加新功能,其中之一正在扩展数据模型。有带有标签的故事,我想将它们合并为Tagaliasgroups。所以我添加了:

import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
class TagAliasGroup {
    Date created = new Date()
    Set aliases
    static hasMany = [aliases: Tag]
[...]

在标签类中,我提到了:

import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
class Tag {
    String tag
    Boolean promoted
    Boolean isCategory
    Date created = new Date()
    TagAliasGroup aliasGroup
[...]

正确更新了DB-Schema,我可以编写新的数据集。但是,当试图访问TagaliasGroup设置的"别名"时,我在Hibernate内部得到无尽的递归,结果是堆叠的异常:

def getAliasList() {
    try
    {
        if(aliasGroup)
        {
            Set al = aliasGroup.aliases
            // al.remove(this)
            return al.join(", ")
        }
        else return ""
    }
    catch(Exception e){
        return e.getMessage()
    }
}

"返回al.join(",")抛出异常,但是对集合的任何其他访问都具有相同的结果。试图评估" AL"时,调试器也会有例外。当那时踏入休眠状态时,当代码试图一遍又一遍地取消代理并解决代理时,它在我看来。

我通过使"别名"瞬态进行了简单的解决方法:

import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
class TagAliasGroup {
    Date created = new Date()
    // Set aliases
    // static hasMany = [aliases: Tag]
    def getAliases() {
        return Tag.findAllByAliasGroup(this)
    }

这很好地工作了,但不能是正确的解决方案。尤其是因为我希望冬眠会缓存结果并因此更有效。

我想念什么?这一定很明显,但我不知道什么。

这是例外:

java.lang.StackOverflowError: null
        at org.apache.commons.logging.impl.SLF4JLocationAwareLog.isDebugEnabled(SLF4JLocationAwareLog.java:67)
        at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.getTargetConnection(LazyConnectionDataSourceProxy.java:429)
        at org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy$LazyConnectionInvocationHandler.invoke(LazyConnectionDataSourceProxy.java:376)
        at org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy$TransactionAwareInvocationHandler.invoke(TransactionAwareDataSourceProxy.java:240)
        at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$5.doPrepare(StatementPreparerImpl.java:162)
        at org.hibernate.engine.jdbc.internal.StatementPreparerImpl$StatementPreparationTemplate.prepareStatement(StatementPreparerImpl.java:186)
        at org.hibernate.engine.jdbc.internal.StatementPreparerImpl.prepareQueryStatement(StatementPreparerImpl.java:160)
        at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.prepareQueryStatement(AbstractLoadPlanBasedLoader.java:257)
        at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeQueryStatement(AbstractLoadPlanBasedLoader.java:201)
        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.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
        at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
        at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
        at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1933)
        at org.hibernate.collection.internal.AbstractPersistentCollection$4.doWork(AbstractPersistentCollection.java:558)
        at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:260)
        at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
        at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
        at org.hibernate.collection.internal.PersistentSet.hashCode(PersistentSet.java:447)
        at org.codehaus.groovy.util.HashCodeHelper.updateHash(HashCodeHelper.java:84)
        at org.codehaus.groovy.util.HashCodeHelper.updateHash(HashCodeHelper.java:84)
        at java.util.HashMap.hash(HashMap.java:339)
        at java.util.HashMap.put(HashMap.java:612)
        at java.util.HashSet.add(HashSet.java:220)
        at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
        at org.hibernate.collection.internal.PersistentSet.endRead(PersistentSet.java:344)
        at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollection(CollectionLoadContext.java:251)
        at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:238)
        at org.hibernate.engine.loading.internal.CollectionLoadContext.endLoadingCollections(CollectionLoadContext.java:211)
        at org.hibernate.loader.plan.exec.process.internal.CollectionReferenceInitializerImpl.endLoading(CollectionReferenceInitializerImpl.java:168)
        at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishLoadingCollections(AbstractRowReader.java:255)
        at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(AbstractRowReader.java:218)
        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.collection.plan.AbstractLoadPlanBasedCollectionInitializer.initialize(AbstractLoadPlanBasedCollectionInitializer.java:100)
        at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:693)
        at org.hibernate.event.internal.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:92)
        at org.hibernate.internal.SessionImpl.initializeCollection(SessionImpl.java:1933)

从这里不断地重复。

我会以我的经验来说明这个答案,以我使用Hasmany,Altersto或任何其他预选赛的经验,这会导致更多的问题。除非您绝对需要它们提供的东西(级联,特定的休眠级缓存等)。只需坚持保留标签上的简单参考,然后从TagaliasGroup中删除" Hasmany",然后使用Dynamic Finder根据您的解决方法加载标签。也就是说,坚持您的设计,我认为您需要"属于",以避免给定标签的tagaliasgroup循环递归。

class Tag {
 ....
 static belongsTo = [TagAliasGroup: aliasGroup]
 ....
}

相关内容

  • 没有找到相关文章

最新更新