Проблема ассоциации запросов Grails
Вопрос
У меня возникли проблемы с написанием запроса для следующих классов домена:
class Person {
static hasMany = [memberships: Membership]
}
class Membership {
static belongsTo = [person: Person, group: Group]
Date joinDate = new Date();
Group group;
Person person;
}
class Group {
static hasMany = [memberships: Membership]
}
По сути, я хочу найти всех людей, принадлежащих к списку групп (скажем, идентификаторы групп (1,2)
.Хитрость здесь в том, что человек должен быть членом обеих групп.Я бы предпочел запрос по критериям, но HQL тоже подойдет.
Обратите внимание, что запрос с чем-то вроде group.id in (1,2)
не сработает, потому что это может быть любая из групп, а не оба.
Решение
Это мой простой подход HQL:
Person.executeQuery("FROM Person x WHERE x IN (SELECT m.person from Membership m WHERE m.group = :group1) AND x IN (SELECT m.person from Membership m WHERE m.group = :group2)", [ group1: Group.get(1), group2: Group.get(2) ])
Ваше здоровье
Другие советы
Возможно, вам не нужен запрос.В классе Person членство представляет собой список объектов Membership.Вы можете узнать, находится ли объект в коллекции (списке), не делая никаких запросов.Что-то вроде этого должно сработать.
if(Person.memberships.contains(Membership.findByPersonAndGroup(person1,group1)) && Person.memberships.contains(Membership.findByPersonAndGroup(person1,group2))){
...do something...
}
Вероятно, другое решение проще, но я думаю, что это просто еще один вариант.
Ваше здоровье
Интересная проблема.Не уверен, что предыдущие решения являются общими по количеству совпадающих групп - я думаю, что на данный момент оно зафиксировано на уровне 2.Хотя, наверное, есть способ сделать их переменными.
Другой способ, который я описываю здесь, на доске объявлений Grails - http://www.nabble.com/has-many-through-relationship-query---GORM--td23438096.html
Включая комментарий автора Роберта Фишера «Сохраняемость Grails с помощью GORM и GSQL».
@chadsmall
Вот еще один подход, позволяющий избежать необходимости программного добавления подзапросов к предложению WHERE:
Запрос:
SELECT count(person.id) AS numPeople, person
FROM Person as person
INNER JOIN
person.memberships AS mships
WITH mships.group.id IN (:groupIds)
GROUP BY person.id
HAVING COUNT(person.id) = (:numOfGroupIds)
И несколько примеров значений:
[
groupIds: [8,9,439,86843]
numOfGroupIds: 4
]
Часть этого запроса до GROUP BY собирает всех людей, которые соответствуют любой групп.Затем, сгруппировав по человеку и проверив, что количество результатов равно количеству групп в списке, вы можете убедиться, что этот человек является членом всех указанных групп.