1

我正在处理的项目中有一些代码,其中动态查找器在一个代码分支中的行为与在另一个代码分支中的行为不同。

这行代码返回我所有的广告商(其中有 8 个),无论我在哪个分支。

Advertiser.findAllByOwner(ownerInstance)

但是当我开始添加条件时,事情变得很奇怪。在分支 A 中,以下代码返回我的所有广告客户:

Advertiser.findAllByOwner(ownerInstance, [max: 25])

但在分支 B 中,该代码仅返回 1 个广告客户。

应用程序代码的更改似乎不可能影响动态查找器的工作方式。我错了吗?还有什么可能导致这不起作用吗?

编辑

我被要求发布我的班级定义。我不会发布所有内容,而是发布我认为重要的部分:

static mapping = {
    owner fetch: 'join'
    category fetch: 'join'
    subcategory fetch: 'join'
}

static fetchMode = [
      grades: 'eager',
      advertiserKeywords: 'eager',
      advertiserConnections: 'eager'
]

此代码存在于分支 B 中,但在分支 A 中不存在。当我将其拉出时,事情现在按预期工作。

我决定用这个代码做更多的挖掘,看看我能观察到什么。当我使用withCriteria而不是动态查找器时,我发现了一些有趣的东西:

Advertiser.withCriteria{owner{idEq(ownerInstance.id)}}

我发现这返回了数千个重复项!所以我尝试使用listDistinct

Adviertiser.createCriteria().listDistinct{owner{idEq(ownerInstance.id)}}

现在这将返回我的所有 8 个广告商,没有重复。但是如果我试图限制结果呢?

Advertiser.createCriteria().listDistinct{
    owner{idEq(ownerInstance.id)}
    maxResults 25
}

现在这会返回一个结果,就像我的动态查找器一样。当我加速maxResults到 100K 时,现在我得到了全部 8 个结果。

那么发生了什么?似乎连接或急切获取(或两者)生成的 sql 返回了数千个重复项。默认情况下,Grails 动态查找器必须返回不同的结果,所以当我不限制它们时,我没有发现任何奇怪的东西。但是一旦我设置了一个限制,由于记录是按 ID 排序的,前 25 条记录都将是重复记录,这意味着只会返回一个不同的记录。

至于joins和eager fetching,我不知道代码试图解决什么问题,所以我不能说是否有必要;问题是,为什么在我的班级中有这段代码会产生这么多重复?

4

2 回答 2

1

我发现添加了 Eager fetching(许多级别的深度)是为了加快某些报告的呈现速度,因为正在进行数百次查询。曾尝试过按需获取,但其他开发人员很难使用查找器或 Grails 标准深入一层以上。

所以对上述问题的一般答案是:我们需要找到一种方法来对单个查询进行渴望获取,而不是默认情况下会在其他地方造成巨大的噩梦,这种方法可以在树下超过一层

下一个问题是,怎么做?Grails 对它的支持不是很好,但是可以通过简单地使用 Hibernate 的 Criteria 类来实现。这是它的要点:

        def advertiser = Advertiser.createCriteria()
            .add(Restrictions.eq('id', advertiserId))
            .createCriteria('advertiserConnections', CriteriaSpecification.INNER_JOIN)
                .setFetchMode('serpEntries', FetchMode.JOIN)
                .uniqueResult()

现在广告客户的advertiserConnections, 将被急切获取,advertiserConnections'serpEntries也将被急切获取。您可以根据需要沿着树向下走。然后你可以默认让你的类变得懒惰——它们绝对应该用于hasMany场景。

于 2013-04-25T16:55:29.620 回答
0

由于您的查询正在检索重复项,因此 25 条记录的限制有可能返回相同的数据,因此您的不同将减少到一条记录。

尝试为您的类定义equals()and hashCode(),特别是如果您有一些具有复合主键的类,或者用作hasMany.

我还建议您尝试消除可能性。逐一删除 fetch 和 eager 以查看它如何影响您的结果数据(无限制)。

于 2013-04-23T11:09:46.453 回答