| 

.NET C# Java Javascript Exception

Criteria Frage

Dies ist das Archiv des ehemaligen Forums zum Thema Groovy, Grails, Griffon und Bean Scripting Framework, welches unter groovy-forum.de existierte. Die neue Adresse des Groovy-Forums ist: http://codekicker.de/fragen/themen/groovy.


Criteria Frage

koeberle - 07.09.2010 13:39
Ich habe eine Domainklasse A die kann beliebig viele Relationen zu einer Domainklasse B haben. B hat eine Attribut isOk vom Typ boolean.
Wie muss ich eine Criteria-Anfrage stricken wenn ich alle As haben will wo alle Bs die dazugehören isOk gleich false sind.

Christian


Re: Criteria Frage

koeberle - 07.09.2010 15:29
Ich glaube mein Frage war überhaupt nicht richtig formuliert.
Eigentlich will ich alle As haben, die kein B mit isOk == true haben. Die dürfen aber Bs mit isOk == false haben.
Vielleicht mal ein bisschen konkreter.

class A {
  static hasMany = [bList: B]

  static namedQueries = {
//Das funktioniert (ist trivial)
      withOkBs = {
          bList{eq('isOk', true)}
      }
//Darum gehts
      withOnlyNotOkBs = {
          bList{ne('isOk', true)} //funktioniert nicht *
      }
  }
}

class B {
   A a
   boolean isOk
}

* bList{ne('isOk', true)} das liefert mir alle As die mindestens ein B kennen mit isOk == false, das war es dann wohl nicht.
alternativ dazu not{bList{eq('isOk', true)}} liefert das gleiche.

Es muss im übrigen namedQueries sein, da das nur ein kleiner Teil der Abfrage ist, die ich in verschiedenen Kombinationen verwende. Das ist wirklich praktisch. Und wenn man sich an die Abfragen noch schreibt, dass die aus der Domainklasse kommen, dann kann man sogar später noch verstehen was man da eigentlich gemacht hat (habe letzten erst mal über dem Code gegrübelt warum der eigentlich funktioniert).

Christian


Re: Criteria Frage

milkyman - 07.09.2010 17:22
Ich denke deine Frage war schon ausreichend klar formuliert. Ich kann dir die nur leider nicht als Criteria beantworten, sondern nur als HQL (siehe vorheriger Post).

Das Prinzip ist, dass man sich erst alle As sucht, die min. 1 B mit isOk haben. Die gewünschte Ergebnismenge ist dann die Komplementärmenge der gefundenen As. Das habe ich mit dem "not in Subselect" nachgebaut.

Wenn sich jetzt noch jemand findet, der das als Criteria formulieren kann, bist du am Ziel. :-)

Bye,
Horst


Re: Criteria Frage [mögliche Lösung]

koeberle - 08.09.2010 10:50
Habe eine mögliche Lösung gefunden die sich erst mal alle id's zu den As holt die ich nicht haben will und dann in einer zweite Anfrage die disjunkte Menge von A's holt. Nicht wirklich groovy aber funktioniert.

Language: Groovy
def subQuery = A.createCriteria() def ids = subQuery.list{ projection.proterty('id') bList{eq('isOk', true)} }   def query = A.createCriteria()   def result = query.list{not{'in'('id' ids)}}

Ob ich das auch in den namedQueryies untergekommen werde ich hoffentlich bald erfahren.

Christian


Re: Criteria Frage [mögliche Lösung]

mpuhlmann - 08.09.2010 11:28
Hallo,

scheint ja eine interessante Lösung zu sein. Ich will dich jedoch auf einen kleien Fallstrick hinweisen:

Sobald die Anzahl der IDs aus der ersten Projektion einen Schwellenwert überschreitet (hängt von der verwendeten DB ab - bei Oracle irgendwas um die 1000), kann es sein, dass die DB aussteigt, da das ganze dann zu groß wird. Wir haben dieses "Problem" bei nem normalen Java Projekt + Hibernate mit ner Oracle bekommen.

Ich würd dir also eher von der Lösung abraten, sofern die Anzahl der IDs recht groß werden kann.

Gruss

Marco

Nachtrag:

Anbei ein Link auf ein passendes Hibernate Ticket.


Re: Criteria Frage [mögliche Lösung]

koeberle - 08.09.2010 16:23
Danke für den Hinweis, habe auch ein bisschen Bauchschmerzen dabei. Das Problem hatte ich noch nie. Ich benutze aber auch Postgres und da habe ich schon komplizierte Objektbäume geladen, wo die zentralen Objekte, die ich mir geholt habe gerne mal die Anzahl von mehr als 20000 überschritten hat. Aber ich werde ein Auge darauf haben. Zur Zeit betrifft es etwas 4000 id. Das ganze ist aber erst 4 Monate alt und wächst kontinuierlich.

Christian


Re: Criteria Frage [mögliche Lösung]

koeberle - 08.09.2010 16:33
HSQL habe ich noch nie so richtig gemocht. Habe vorher eine Ganze weile mit Hibernate und JPA gearbeitet, aber dieses Objekte + SQL hat mich immer ein bisschen aus dem Konzept gebracht. Criteria-Queries habe ich erst unter Grails kennen und schätzen gelernt, für einfache Frage sind die auch besser zu lesen als HSQL oder SQL, aber wie man sieht kommt man da auch schneller an die Grenzen. Ansonsten kann ich wirklich manedQueries in den Domainklassen empfehlen. Man sollte zum entwickeln die Criteria-Abfragen erstmal im Controller bauen und wenn die einzelnen funktionierenden Teile in die Domainklasse übertragen, ansonsten wird man wahnsinnig, da ja nach jedem ändern der Donainklasse neu kompiliert und gestartet wird (man wartet sich einfach dumm und dämlich). Auf jeden Fall kann man dann lustige Statements generieren.

Christian


Re: Criteria Frage [mögliche Lösung]

mpuhlmann - 08.09.2010 16:54
Hallo,

das Problem ist weniger das Laden/Aufbauen des Objektbaums, denn mehr die Art, wie Hibernate die Critera umsetzt. Ich würde dir mal empfehlen, dass SQL Logging in Grails zu aktivieren, um dann die beiden Statements deiner Criteria mal ausgedruckt zu bekommen. Du wirst dann erkennen, dass die erste Criteria dir alle betroffenen IDs liefert (is unkritisch) - die zweite erzeugt dann ein SQL Statement, welches in etwa so aussieht:

select ... from ... where ... in (?,?,?,?...?,?,?)

Soll heißen, im Statement werden abhängig von der Anzahl der zuerst gelieferten IDs, Parameter eingebunden, welche dann befüllt werden. Und hier liegt das Problem: Manche Datenbanken unterstützen nur eine begrenzte Anzahl an Parametern in Prepared Statements (MS SQL, Oracle - Postgre gehört meines erachtens nicht dazu).

Weiterhin ist das ganze auch aus Performance Sicht kritisch, da die Parameter des zweiten Statements ja erst alle durch Hibernate gebunden werden müssen. Auch nimmst du der DB Engine damit jegliche Chance, die Query zu optimieren, da die Wahrscheinlichkeit groß ist, dass das Prepared Statement nicht nachgenutzt werden kann.

Ich würd dir wirklich zum Einsatz von HQL raten. Hier kann das ganze dann als Sub-Select realisiert werden und die DB kann (hoffentlich) etwas besser optimieren. Die Anfrage würde dann in etwa so aussehen:

from A as a where not a.id in (select b.a.id from B as b where b.isOk = true)

Auch als resultierendes SQL sieht das ganze dann wesentlich freundlicher aus.

Gruss

Marco


Re: Criteria Frage [mögliche Lösung]

mpuhlmann - 08.09.2010 17:06
Hallo,

du hast schon recht, dass Critera Queries im Wesentlichen leichter zu lesen sind als HQL / SQL. Allerdings ist die API bei weitem nicht so mächtig wie HQL oder gar SQL. Und hier liegt aus meiner Sicht auch ein gravierendes Problem in der massiven Verwendung der Criteria API:

Man abstrahiert massiv von der dahinter liegenden relationalen DB und der dortigen Abfragesprache SQL. Somit wird nicht mehr ersichtlich, was denn wirklich im Untergrund passiert. Oftmals entstehen durch Verwendung der Criteria API plötzlich super komplexe und teilweise recht unperformante SQL Statements.
Und sobald man in den Bereich mehrfacher Joins über mehrere Tabellen inklusive Sub-Selects kommt, wird das ganze über die Hibernate Criteria API absolut unleserlich. Spätestens dann sollte man sich auf HQL oder sogar SQL zurückziehen, da das ganze dann doch leserlicher ist.

Für einfache Abfragen der Art "gib mir mal alle Tasks der letzten x Monate / mit dem Status xyz" ist natürlich der Einsatz von Criterias auch aus meiner Sicht empfehlenswert - gerade als namedQueries in Grails eine interessante Sache.

Ich würde jedem empfehlen, sich nicht nur mit Grails und evtl. Hibernate auseinander zu setzen, sondern auf jeden Fall auch das Thema SQL, relationale DBs etc. zu betrachten, da man bereits sehr viele Design-Fehler machen kann, wenn man sich nur auf die objektorientierte Seite stürzt.

Gruss

Marco


Re: Criteria Frage [mögliche Lösung]

koeberle - 08.09.2010 17:16
Da gebe ich dir gerne Recht. Ich schau mir schon gar nicht mehr an was Hibernate da produziert, da wird dem Datenbankpuristen in mir immer ganz übel. Bloß ist in 90% der Fälle die mir untergekommen sind Performance nicht relevant. Es gab in unserer Firma bis jetzt nur einen Fall wo wir wirklich auf Seiten der DB und er Abfragen optimieren mussten und da ging es über ca. 10 Tabellen a 50 Mio. Datensätze. Auf der anderen Seite haben wir kaum Traffic, das kann dann wirklich bei relativ einfachen Abfragen zum Problem werden.

Christian


Stelle deine Groovy-Frage jetzt!


Diese Seite zeigt den Thread "Criteria Frage" der ehemaligen Webseite groovy-forum.de, welche durch einen Serverunfall zerstört wurde. codekicker.de hat viele Konversationen über die beliebte Programmiersprache Groovy und zugehörige Frameworks wie das Grails-Framework retten können.

Hast Du eine Frage zum Thema Groovy, Grails oder allgemein Java? Viele ehemalige groovy-forum.de Mitglieder beantworten dir auf codekicker.de deine Frage! Stelle jetzt eine Frage!

Viele weitere Diskussionen zu Grails und Groovy befinden sich auf der Threadübersicht des alten groovy-forum.de.