Domanda

Ho problemi a scrivere una query per le seguenti classi di dominio:

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

Fondamentalmente, voglio trovare tutte le persone che appartengono a un elenco di gruppi (supponiamo che gli ID di gruppo siano (1,2) . Il trucco qui è che la persona deve essere un membro di entrambi gruppi. Preferirei una query di criteri, ma anche HQL è ok.

Nota che eseguire query con qualcosa come group.id in (1,2) non funzionerà perché può essere uno qualsiasi dei gruppi, non entrambi .

È stato utile?

Soluzione

Questo è il mio semplice approccio 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) ])

Saluti

Altri suggerimenti

Forse non hai bisogno di una query. Nella classe Person, membership è un elenco di oggetti Membership. Puoi scoprire se un oggetto si trova in una raccolta (elenco) senza effettuare alcuna query. Qualcosa del genere dovrebbe fare il lavoro.

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

Probabilmente l'altra soluzione è più semplice, ma penso che questa sia solo un'altra opzione.

Saluti

Collezioni Groovy

Problema interessante. Non sono sicuro che le soluzioni precedenti siano generiche sul numero di gruppi abbinati - nei casi finora è fissato a 2 credo. Anche se c'è probabilmente un modo per renderli variabili.

Un altro modo che descrivo qui nella bacheca dei grails - http://www.nabble.com/has-many-through-relationship-query---GORM--td23438096.html

Incluso il commento dell'autore, Robert Fischer, di "Grails Persistence con GORM e GSQL".

@chadsmall

Ecco un altro approccio che evita di dover aggiungere a livello di codice le subquery alla tua clausola WHERE:

Domanda:

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 alcuni valori di esempio:

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

La parte di questa query fino a GROUP BY cattura tutte le persone che corrispondono a qualsiasi dei gruppi. Quindi, raggruppando per persona e verificando che il numero di risultati sia uguale al numero di gruppi nell'elenco, puoi verificare che questa persona sia membro di tutti i gruppi specificati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top