2011-04-05 4 views
0

J'ai une requête dans HQL qui fonctionne pleinement. Cependant, je voudrais l'exprimer dans le formulaire Critères, qui est plus facile à lire et à maintenir.Transformer HQL en critères

Voici le scénario: J'ai des travailleurs, des gens et des paiements. Un travailleur est une personne plus un type d'emploi (une personne, dans cette application, peut être deux travailleurs avec des types d'emploi distincts en même temps). Il y a beaucoup de paiements, et il pourrait y en avoir plus d'un pour un travailleur. J'ai besoin d'obtenir chaque travailleur une fois, puis la somme de toutes les valeurs de paiement pour ce travailleur. Ce sont les requêtes HQL:

1- Obtenez tous les paiements:

Payment.findAll("from Payment as p where p.month = :m and p.year = :y group by p.worker.id, p.worker.person.id", [m: paymentsMonth, y: paymentsYear]) 

2- Itère les paiements, pour chacun d'eux je reçois la somme des paiements pour ce travailleur de cette façon (il est le paiement):

def totalLiquidValue = Payment.executeQuery('''select sum(liquidValue) from Payment where 
               month = :m and 
               year = :ar and 
               worker = :w''', 
               [m: it.paymentMonth, ar: it.year, w: payment.worker]) 
               .first() 

il fonctionne, mais pas les critères que j'ai essayé d'écrire pour le remplacer:

1-

def payments = Payment.withCriteria { 
        worker { 

         projections { 
          groupProperty('jobType') 
         } 

         person { 
          projections { 
           groupProperty('id') 
          } 
         } 
        } 

        eq('month', paymentsMonth) 
        eq('year', paymentsYear) 
       } 

Il échoue avec "com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'person_ali2_.msid' dans 'liste des champs'"

'MSID' est en fait le nom de la 'id' champ dans la base de données. Cela se fait via l'ID de mappage dans la classe de domaine Worker.

Voyez-vous de nouvelles possibilités?

Merci

Mise à jour:

Nous avons besoin d'utiliser des bases de données existantes, fournies par le client. Pour une meilleure organisation, les classes que nous utilisons sont représentées sous forme de vues, nommées "legacy_tablename", et tout ce qui est exclusivement dans notre partie du système se trouve dans une base de données séparée, donc les vues référencent les tables dans d'autres bases de données. besoin de traiter plusieurs bases de données dans le code. C'est pourquoi parfois les noms de tables sont spécifiés.

Les classes de domaine sont grandes, mais ce sont les détails importants à leur sujet:

class Payment{ 

    Integer year 
    Integer month 

    Worker worker 

    BigDecimal liquidValue 

} 

class Worker { 
    Person person 
    Integer jobType 

    static mapping = { 
     table("legacy_worker") 
     id(composite: ["jobType", "person"]) 
     person(column: "msid", fetch: "join") 
    }  
} 

class Person { 
    String id 

    static mapping = { 
     table("legacy_person") 
     id(column:"msid", generator: "assigned") 
    } 
} 

Merci

+0

à partir de Payment as p * where et * p.month =: m relly cela fonctionne en HQL? –

+0

Pourriez-vous fournir les objets de domaine pour le paiement, le travailleur et la personne? Cela nous aiderait tous à mieux comprendre les détails. –

+0

Pollano, désolé. Le code n'est pas en anglais, donc je le mets ici et ensuite traduis les noms des variables, ce 'et' était une faute de frappe. – Gabriel

Répondre

0
 def payments = Payment.withCriteria { 
      createAlias('worker','w') 
      projections { 
       property('w.id') 
       groupProperty('w.jobType') 
       groupProperty('w.person')      
      } 
      eq('month', paymentsMonth) 
      eq('year', paymentsYear) 
     } 

Au-dessus de requête vous donnera la liste des listes, où 1er élément serait travailleur, 2ème serait jobType et 3ème serait l'objet personne qui a donné le mois et l'année.

def payments = Payment.withCriteria { 
      projections { 
      sum('liquidValue') 
      } 
      eq('month', paymentsMonth) 
      eq('year', paymentsYear) 
      eq('worker',worker) 
     } 
+0

Merci, je ne savais pas que c'était la notation pour les projections internes. Mais, étrangement, la requête renvoie une liste d'entiers, qui sont les types de travail des travailleurs. J'ai essayé d'ajouter une projection de propriété ("worker"), mais elle échoue, disant que le worker ne correspond pas à une seule colonne. – Gabriel

+0

J'ai mis à jour la réponse, pour retourner l'objet de travail le long de la première requête. Espérons que cela fonctionne? –

+0

Malheureusement, il échoue avec "org.hibernate.QueryException: la propriété ne correspond pas à une seule colonne: worker", dans la propriété ('worker'). Je pense que c'est parce que Grails ne gère pas correctement l'ID composé (dans Worker) dans ces relations. – Gabriel

Questions connexes