Pergunta

Estou tendo dificuldade para escrever uma consulta para as seguintes classes de domínio:

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

Basicamente, eu quero encontrou todas as pessoas que pertencem a uma lista de grupos (ids grupo dizem de Let são (1,2). O truque aqui é que a pessoa deve ser um membro de ambos os grupos. Eu preferiria uma consulta critérios, mas HQL é ok também.

Note que a consulta com algo como group.id in (1,2) não vai funcionar porque pode ser qualquer um dos grupos, não ambos .

Foi útil?

Solução

Essa é a minha abordagem HQL simples:

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

Felicidades

Outras dicas

Talvez você não precisa de uma consulta. Na classe Pessoa, adesões é uma lista de objetos de adesão. Você pode encontrar se um objeto está em uma coleção (lista) sem fazer qualquer consulta. Algo como isso deve fazer o trabalho.

if(Person.memberships.contains(Membership.findByPersonAndGroup(person1,group1)) && Person.memberships.contains(Membership.findByPersonAndGroup(person1,group2))){
  ...do something...
}

Provavelmente a outra solução é simplier, mas acho que isso é apenas uma outra opção.

Felicidades

Groovy coleções

problema interessante. Não tenho certeza as soluções anteriores são genéricos sobre o número de grupos emparelhados - nos casos até agora, é fixado em 2 eu acho. Embora provavelmente há uma maneira de torná-los variável.

Outra maneira que eu descrevo aqui nas grails MessageBoard - http://www.nabble.com/has-many-through-relationship-query---GORM--td23438096.html

Incluindo comentário do autor, Robert Fischer, de "Grails Persistence com GORM e GSQL".

@chadsmall

Aqui está uma outra abordagem que evita ter que anexar programaticamente subconsultas à sua cláusula WHERE:

Inquérito:

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)

E alguns valores de exemplo:

[
  groupIds: [8,9,439,86843]
  numOfGroupIds: 4
]

A parte desta consulta até o GROUP BY agarra todas as pessoas que correspondem qualquer dos grupos. Então, agrupando por pessoa e verificar o número de resultados é igual ao número de grupos na lista, você pode verificar que esta pessoa é um membro de todos os grupos especificados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top