Grails dynamic finder能被应用程序代码破坏吗?
我正在处理的项目中有一些代码,其中动态查找器在一个代码分支中的行为与在另一个代码分支中的行为不同 这行代码返回我所有的广告商(有8个),不管我在哪个分支Grails dynamic finder能被应用程序代码破坏吗?,grails,branch,gorm,dynamic-finders,Grails,Branch,Gorm,Dynamic Finders,我正在处理的项目中有一些代码,其中动态查找器在一个代码分支中的行为与在另一个代码分支中的行为不同 这行代码返回我所有的广告商(有8个),不管我在哪个分支 Advertiser.findAllByOwner(ownerInstance) 但当我开始添加条件时,事情变得很奇怪。在分支A中,以下代码返回我的所有广告客户: Advertiser.findAllByOwner(ownerInstance, [max: 25]) 但在分支B中,该代码只返回1个广告客户 应用程序代码中的更改似乎不可能影响
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中不存在。当我将其取出时,一切都按预期进行
我决定用现在的代码做更多的挖掘,看看我能观察到什么。当我使用带条件的而不是动态查找器时,我发现了一些有趣的东西:
Advertiser.withCriteria{owner{idEq(ownerInstance.id)}
我发现这封信退回了数千份副本!因此,我尝试使用listdinctinct
:
Adviertiser.createCriteria().listDistinct{owner{idEq(ownerInstance.id)}
现在,这将返回我所有的8个广告商,没有重复。但是如果我试图限制结果呢
Advertiser.createCriteria().listDistinct{
owner{idEq(ownerInstance.id)}
maxResults 25
}
现在它返回一个结果,就像我的DynamicFinder一样。当我把maxResults
调到100K时,现在我得到了全部8个结果
发生了什么事?似乎连接或急切抓取(或两者)生成了返回数千个重复项的sql。Grails dynamic Finder在默认情况下必须返回不同的结果,所以当我没有限制它们时,我没有注意到任何奇怪的事情。但一旦我设置了一个限制,因为记录是按ID排序的,所以前25条记录都是重复记录,这意味着只会返回一条不同的记录
至于连接和急切抓取,我不知道代码试图解决什么问题,所以我不能说是否有必要;问题是,为什么我的类中的这段代码会生成如此多的重复项?由于您的查询检索的是重复项,有可能25条记录的限制返回相同的数据,因此您的distinct将减少为一条记录
尝试为类定义equals()
和hashCode()
,特别是如果有些类使用复合主键,或者用作hasMany
我还建议你尽量消除这些可能性。逐个删除获取和渴望的数据,查看它对结果数据的影响(没有限制)。由于您的查询正在检索重复数据,25条记录的限制可能会返回相同的数据,因此您的distinct将减少为一条记录
尝试为类定义equals()
和hashCode()
,特别是如果有些类使用复合主键,或者用作hasMany
我还建议你尽量消除这些可能性。一个接一个地删除抓取和急切抓取,以查看它对结果数据的影响(没有限制)。我发现,为了加快某些报告的呈现,添加了急切抓取(很多级别),因为进行了数百次查询。有人尝试按需抓取,但其他开发人员很难使用Finder或Grails标准深入到一个以上的层次
因此,对上述问题的一般答案是:我们需要找到一种方法,在一个查询上进行即时抓取,而不是在默认情况下进行即时抓取,因为这可能会在其他地方造成巨大的噩梦
下一个问题是,如何解决?Grails并没有很好地支持它,但可以通过简单地使用Hibernate的Criteria类来实现。以下是它的要点:
def advertiser = Advertiser.createCriteria()
.add(Restrictions.eq('id', advertiserId))
.createCriteria('advertiserConnections', CriteriaSpecification.INNER_JOIN)
.setFetchMode('serpEntries', FetchMode.JOIN)
.uniqueResult()
现在广告客户的广告客户连接
,将被急切地获取,而广告客户连接
“毒蛇
也将被急切地获取。你可以在树下走到你需要的地方。然后你可以让你的类在默认情况下处于惰性状态,这对于有很多
场景来说是绝对应该的。我发现,为了加速某些报告的呈现,添加了急切抓取(很多级别),因为有数百个查询正在进行。有人尝试按需抓取,但其他开发人员很难使用Finder或Grails标准深入到一个以上的层次
因此,对上述问题的一般答案是:我们需要找到一种方法,在一个查询上进行即时抓取,而不是在默认情况下进行即时抓取,因为这可能会在其他地方造成巨大的噩梦
下一个问题是,如何解决?Grails并没有很好地支持它,但可以通过简单地使用Hibernate的Criteria类来实现。以下是它的要点:
def advertiser = Advertiser.createCriteria()
.add(Restrictions.eq('id', advertiserId))
.createCriteria('advertiserConnections', CriteriaSpecification.INNER_JOIN)
.setFetchMode('serpEntries', FetchMode.JOIN)
.uniqueResult()
现在广告客户的广告客户连接
,将被急切地获取,而广告客户连接
“毒蛇
也将被急切地获取。你可以在树下走到你需要的地方。然后,您可以让您的类在默认情况下处于惰性状态-对于有许多场景,它们肯定应该是惰性的。您可以分享广告商的定义吗?您确定两者的所有者身份相同吗?您认为应用程序不应影响此行为。更可能的原因是,您指向不同分支中的两个不同数据库,或者一个分支进行了验证,而另一个分支没有,您在一个fixture或Bootstrap中创建了8个广告客户,但创建失败。记住,第一行