#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