用于修复列表中最大表达式数的重构闭包条件是1000

时间:2018-05-03 12:31:05

标签: java grails groovy closures criteria

我在我必须维护的应用程序中找到了以下代码

 def addCriteriaClosure = { criteriaList ->
   criteriaList.inList('id', paketInstance.dateien.id)
 }
 def criteria = Datei.createCriteria()
 def result = criteria.list() {
   addCriteriaClosure.call(criteria)
 }

可悲的是,此调用会导致以下错误:

java.sql.SQLSyntaxErrorException: ORA-01795: maximum number of expressions in a list is 1000

事实是paketInstance.dateien包含超过1000行/项。 为避免此错误,我尝试了以下方法:

def addCriteriaClosure = { criteriaList ->
  paketInstance.dateien.asList().collate(999).each {
    criteriaList.inList('id', paketInstance.dateien.asList().collate(999).id)
  }
}

但这会导致此错误:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.Long

我知道解决方案是使用collate(999)操作,但我不知道如何将其与初始方法相结合以获得预期结果。

编辑#1

不幸的是我无法编辑这部分实现:

 def criteria = [Type].createCriteria()
 def result = criteria.list() {
   addCriteriaClosure.call(criteria)
 }

将具体类型传入方法的位置。 我只能编辑addCriteriaClosure的定义 例如:

 def addCriteriaClosure = { criteriaList ->
   criteriaList.inList('id', paketInstance.dateien.id)
 }

编辑#2

当我按照以下

设计我的标准闭包时
def l = paketInstance.dateien.id.toList().collate(999)
        def addCriteriaClosure = { criteriaList ->

            l.each {
                a -> criteriaList.inList("id", a.toList())
            }
        }

Hibernate创建一个SQL-Statement,它将列表拆分为单独的in WHERE子句。但问题是这两个条款与AND相关联。为了得到正确的结果,我需要OR用于两个列表,而不是生成的sql中的AND

制作了SQL:

 select this_.id as id51_0_, this_.version as version51_0_, this_.aktualisiert_am as aktualis3_51_0_, this_.name as name51_0_, this_.nummer as nummer51_0_, this_.pfad as pfad51_0_, this_.status as status51_0_, this_.typ as typ51_0_ from datei this_ where this_.id in (?, ?, ?, ?, ?, ?....)  and this_.id in (?, ?, ?, ?, ?, ?, ?....)

所以我需要and this_.id

而不是or this_.id in

3 个答案:

答案 0 :(得分:1)

尝试这样的方法:

def manyThingsToFind = [...list of more than 1000 things...]
def clauseLimit = 999
def results = YourDomainObject.createCriteria().listDistinct {
  or {
    manyThingsToFind.collate(clauseLimit)?.each { collatedList ->
      'in'("fieldToMatch", collatedList)
    }
  }
}

如果您愿意,可以将实际标准分解为闭包。

答案 1 :(得分:0)

如果要将ID列表限制为不超过999项,则应使用

def idList = paketInstance.dateien.asList().id[0..<999]

除了

丢弃一些要比较的ID只是因为Oracle在in谓词中不允许超过1000个项目似乎不是一个好的解决方案。假设从数据库中检索到此ID列表,您应该能够使用子查询/联接来执行比较。

答案 2 :(得分:0)

找到解决方案

def collatedFileList = paketInstance.dateien.id.toList().collate(999)
        def addCriteriaClosure = { criteriaList ->
            criteriaList.or {
                collatedFileList.each {
                    l -> criteriaList.inList("id", l.toList())
                }
            }
        }
  1. 解决了我必须面对的问题
  2. 了解关闭/标准的事情