Запрос критериев Grails, повторяющий повторяющиеся экземпляры

#grails #criteria

#grails #критерии

Вопрос:

У меня есть вызываемый класс домена Order , и этот класс имеет hasMany отношение к Item классу. Когда я запрашиваю список заказов с определенными ограничениями, я получаю столько экземпляров Order , сколько есть items .

Итак, например Order , в экземпляре есть ссылки на 3 экземпляра Item then , вызов criteria Order возвращает 3 повторяющихся экземпляра Order . Я не уверен, но стоит ли упоминать, что класс домена Order имеет fetchMode значение "eager" .

Я действительно озадачен тем, что там происходит. Любая помощь в этом отношении будет высоко оценена. Фрагмент кода прилагается:

 def clazz = "cust.Order"
def criteria = clazz.createCriteria()
        println("clazz == " Order.list())// returning correct data i.e unique instance of order
        def filter = {
                    // trimmed down all filtering criteria for debugging
            }//close filter
        List results = criteria.list(max:params?.max,offset:params?.offset,filter)
            results.each{Object data->
                println(data.getClass())
            }
        println("results == " results)
  

Еще раз спасибо

Ответ №1:

Одним из решений является использование этого в вашем запросе:

 resultTransformer org.hibernate.Criteria.DISTINCT_ROOT_ENTITY
  

Ответ №2:

Если вы вызываете criteria.listDistinct вместо criteria.list дубликатов, они будут устранены

Комментарии:

1. Следует отметить, что это может привести к изменению типа результатов из результирующего набора в список объектов домена (в некоторых случаях прерывается разбивка на страницы).

2. Вы не можете добавлять параметры, такие как max или offset, с помощью listDistinct (метод listDistinct() плохо работает с параметрами разбиения на страницы maxResult и firstResult . Если вам нужны разные результаты с разбиением на страницы, в настоящее время мы рекомендуем использовать HQL), по крайней мере, в grails 2.x или ниже

Ответ №3:

Criteria API — это просто оболочка для построения SQL-запроса. В вашем случае в рассматриваемом запросе есть объединения (из-за быстрой выборки), и он возвращает декартово произведение заказов и их соответствующих элементов. Каждая возвращенная строка включается в результаты как отдельный экземпляр Order.

Самый простой способ удалить дубликаты — поместить все результаты в набор, например:

 def resultSet = new HashSet()
resultSet.addAll(results)
println("results == "   resultSet)
  

Комментарии:

1. Это сработало, но есть ли лучший способ решить эту проблему? Например, изменение режима выборки во время запроса или что-то в этом роде?

Ответ №4:

Вы также можете использовать динамические средства поиска, как в Order.findAllBy * . В зависимости от того, насколько сложен ваш фильтр, это может быть легко или сложно 🙂

Комментарии:

1. Мой фильтр довольно сложный и очень динамичный, я не думаю, что findBy будет работать в этом случае. Фильтр также применяется к вложенным объектам. Это одна из причин, по которой я решил использовать критерии вместо собственного SQL