我最近从另一个人那里接手了Grails项目。

我正在使用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]
[...]

在Tag类中,我提到了这一点:
import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class Tag {
    String tag
    Boolean promoted
    Boolean isCategory
    Date created = new Date()

    TagAliasGroup aliasGroup

[...]

数据库架构已正确更新,我可以编写新的数据集。但是,当尝试访问TagAliasGroup中的“别名”集时,我在Hibernate中得到了无限的递归,并因此得到了StackOverflow异常:
def getAliasList() {
    try
    {
        if(aliasGroup)
        {
            Set al = aliasGroup.aliases
            // al.remove(this)

            return al.join(", ")
        }
        else return ""
    }
    catch(Exception e){
        return e.getMessage()
    }
}

“return al.join(”,“)”引发异常,但是对Collection的任何其他访问都具有相同的结果。尝试评估“al”时,调试器也会获得异常。
在那时进入Hibernate时,在我看来,代码试图一遍又一遍地取消引用和解析TagAliasGroup的代理。

通过使“别名”成为 transient ,我做了一个简单的解决方法:
import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class TagAliasGroup {
    Date created = new Date()

    // Set aliases
    // static hasMany = [aliases: Tag]

    def getAliases() {
        return Tag.findAllByAliasGroup(this)
    }

这是完美的工作,但它不是正确的解决方案。尤其是因为我希望休眠可以缓存结果,因此可以提高效率。

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

这是异常(exception):
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,belongsTo或其他任何限定词的经验中,我将用这个答案作为前缀,这会导致更多的问题而不是有用的问题。除非您绝对需要它们提供的功能(级联,特定的休眠级别缓存等)。只需坚持使用Tag上的简单参考,然后从TagAliasGroup中删除“hasMany”,然后根据您的解决方法使用动态查找器加载标签即可。就是说,坚持您的设计,我认为您需要使用'belongsTo'来避免对给定标签进行对TagAliasGroup的循环反向引用的递归。

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

09-11 19:19