Критерий закрытия рефакторинга для исправления максимального числа выражений в списке - 1000 - PullRequest
0 голосов
/ 03 мая 2018

Я нашел следующий фрагмент кода в приложении, которое я должен поддерживать

 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, который разбивает списки на отдельные in предложения WHERE. Но проблема в том, что эти два предложения связаны с AND. Чтобы получить правильный результат, мне нужно OR для двух списков, а не AND в сгенерированном sql

выданный 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 голосов
/ 03 мая 2018

Попробуйте использовать такой подход:

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)
    }
  }
}

Вы можете разбить фактические критерии на закрытие, если хотите, как вы уже сделали.

0 голосов
/ 07 мая 2018

Нашли решение

def collatedFileList = paketInstance.dateien.id.toList().collate(999)
        def addCriteriaClosure = { criteriaList ->
            criteriaList.or {
                collatedFileList.each {
                    l -> criteriaList.inList("id", l.toList())
                }
            }
        }
  1. Решает проблему, с которой мне пришлось столкнуться
  2. Много узнал о закрытии / критериях
0 голосов
/ 03 мая 2018

Если вы хотите ограничить список идентификаторов не более чем 999 элементами, вы должны использовать

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

Помимо

Отбрасывание некоторых идентификаторов для сравнения только потому, что Oracle не допускает более 1000 элементов в предикате in, не кажется хорошим решением. Предполагая, что этот список идентификаторов получен из базы данных, вы должны иметь возможность использовать подзапрос / объединение для выполнения сравнения.

...