Als wir das letzte Mal gelernt haben, wie man Kriterien verwendet, um verwandte Operationen miteinander auszuführen. Da Kriterien jedoch nicht die von Hibernate offiziell empfohlene Abfragemethode sind, verwenden wir sie nicht viel. Schauen wir uns nun die offiziell empfohlene HQL an und erfahren Sie, wie mächtig sie zusammen ist.
Was ist der Unterschied zwischen HQL oder Hibernate -Query -Anweisung und SQL? Der Unterschied zwischen einem Buchstaben, haha.
Natürlich ist dies nicht der Fall. Der Unterschied zwischen HQL und SQL liegt in den verschiedenen Ideen. HQL verwendet eine objektorientierte Richtung zur Abfrage, während SQL eine Abfrage für zweidimensionale Datenbanktabellen verwendet. Was hier enthalten ist, ist der Unterschied in den Ideen. HQL ist eigentlich SQL und wird von Hibernate hergestellt, um SQL intern zu konvertieren und zu generieren.
1) Schauen wir uns ohne weiteres auf seine Kraft an.
vom Benutzer
Dieser Code ist sehr vertraut, da wir häufig aus Tabellennamen in SQL verwendet werden. Der Unterschied hier ist jedoch, dass der Benutzer hier nicht der Tabellenname ist, sondern der Name der Entitätsklasse, und der Hibernate hilft uns, die Karte zuzubereiten.
Associate SQL -Anweisungen, wenn wir ein bestimmtes Attribut finden und es bedingt ein bestimmtes Attribut beschränken möchten, können wir eine ähnliche Anweisung erhalten:
Wählen Sie usr.name, usr.age vom Benutzer, wobei usr.age> 20 und usr.age <60
Auf diese Weise fanden wir die Namen und Alter der Benutzer über 20 und jünger als 60. Es ist leicht zu verstehen.
Das und, oder wie, <,>, = und so weiter in SQL -Anweisungen können in HQL verwendet werden.
Es ist zu beachten, dass beim Abfragen mehrerer Attribute das zurückgegebene Ergebnis ein Objekt [] -Array ist und wenn nur ein einzelner ein einziger zurückgegeben wird, wird das Objekt zurückgegeben. Dies erfordert unterschiedliche Parsingmethoden, sodass Sie bei der Abfrage darauf achten müssen.
2) Natürlich haben wir früher gesagt, dass HQL objektorientiert ist, und wenn wir dies tun, ist es keine objektorientierte Idee. Lassen Sie es uns ändern:
Wählen Sie einen neuen Benutzer (usr.name, usr.age) aus dem Benutzer usr, wo usr.age> 20Auf diese Weise setzen wir das Abfrageergebnis in das Benutzerobjekt ein. Beachten Sie, dass der Benutzerkonstruktor hier aufgerufen wird. Es muss einen Benutzerkonstruktor geben, der in der Benutzerklasse zwei Parameter empfängt, andernfalls wird ein Fehler gemeldet. Die Fehlermeldung ist ungefähr wie folgt:
Der geeignete Konstruktor in der Klasse kann nicht lokalisiert werden [org.hibernate.tutorial.domain8.User]
Es kann keinen geeigneten Konstruktor finden. Es ist sehr klar, dass nur den Konstruktor hinzugefügt wird, der die entsprechenden Parameter empfängt.
Beachten Sie, dass wir beim Überprüfen der entsprechenden ID nicht herausgefunden haben. Wenn wir die SaveORUpdate -Methode zu diesem Zeitpunkt aufrufen, führte sie den gespeicherten Betrieb tatsächlich durch.
Schauen wir uns den Testcode an:
Nachdem ich die obige Abfrageanweisung ausgeführt habe, führe ich die folgenden Vorgänge aus:
while (iter.hasnext ()) {user user = (user) iter.next (); user.setName ("sun2"); Session.SaveorUpdate (Benutzer); } Zu diesem Zeitpunkt lautet die Hibernate -Aussage:
Hibernate: In den Benutzer (user_name, Alter) einfügen (?,?)
Es fügt eine neue ein, kein Update.
Wenn wir es dann aktualisieren müssen, müssen wir die ID gemeinsam herausfinden:
Wählen Sie einen neuen Benutzer (usr.name, usr.age, usr.id) von Benutzer usr, wobei USR.age> (AVG (usr.age) von usr)
Denken Sie daran, den Benutzerkonstruktor zu ändern.
Zu diesem Zeitpunkt führen wir unseren Testcode erneut aus und Sie erhalten:
Hibernate: User Set user_name =?, Age =? wo user_id =?
Wählen Sie usr.name aus dem Benutzer usr, wobei usr.age> (avg (usr.age) von usr)
Dieser HQL erkennt den Namen des älteren Benutzers als das Durchschnittsalter.
4) In Hibernate 3 können wir Objekte leicht aktualisieren und löschen, ohne zuerst laden und dann in 2. löschen zu müssen. Wir können es direkt in einer Anweisung tun:
Aktualisieren Sie den Benutzer set name = '123123' wobei name = 'sun33'
Aussagen löschen sind ähnlich:
Benutzer löschen wobei Name = '123123'
5) Es ist auch leicht zu gruppieren und zu sortieren. Verwenden Sie die Gruppe einfach von und bestellen von, und ich werde zu diesem Zeitpunkt nicht mehr darüber sprechen.
6) Wir sehen, dass die oben genannten direkt in Abfragen oder Update geschrieben sind. Wenn wir eine dynamische Zuordnung benötigen oder zu viele Aufgaben vorhanden sind, können wir keine Zeichenfolgen wie JDBC spleißen. Es wird geschätzt, dass es mehr als 5 gibt und jeder im Projektteam mich schimpfen möchte, haha.
Es ist besser, eine moderne Methode zu verwenden, stattdessen Platzhalter zu verwenden und dann bestimmte Werte festzulegen.
Unser direkter Code:
Query query = session.createquery ("Neuen Benutzer (usr.name, usr.age, usr.id) aus dem Benutzer usr where usr.name =?"); Query.SetString (0, "Shun"); Wir sehen, dass diese Methode der vorbereiteten Stattierung ähnlich ist, die wir direkt verwenden. Es wird durch Set *** gesetzt, aber der Unterschied besteht darin, dass die Position hier von 0 beginnt, während der vorbereitete Anschluss von 1 beginnt. Achten Sie also hier besonders darauf.
Es gibt auch eine Sitzungsmethode in Hibernate2, aber da ich jetzt 3 verwende, werde ich nicht viel darüber sagen.
Der oben verwendete Platzhalter wird als Order -Platzhalter bezeichnet, und es gibt einen anderen, der als Referenzplatzhalter bezeichnet wird. Schauen wir uns an:
Query query = session.createquery ("Neuen Benutzer (usr.name, usr.age, usr.id) aus dem Benutzer usr wobei usr.name =: name"); Query.SetParameter ("Name", "Shun"); Ich habe gesehen, dass es so etwas wie: Name in unserer HQL -Aussage gibt. Dies ist ein Referenzplatzhalter. Wir müssen den Wert nur durch SetParameter später einstellen. Beachten Sie, dass der erste Parameter hier dem Platzhalterwert in der HQL -Anweisung entsprechen muss.
Natürlich können einige Leute sagen, dass dies nicht objektorientiert ist. Gehen wir also erneut zu Objektorientierungen:
Erstellen Sie zunächst eine Klasse, um den von uns abfrage
public class userQuery {private Zeichenfolge Name; privates int Alter; // Die Get/Set -Methode weglassen} query query = session.createquery ("Neuen Benutzer (usr.name, usr.age, usr.id) aus dem Benutzer usr, wobei usr.name =: name"); UserQuery uq = new userQuery (); Uq.SetName ("Shun"); query.setProperties (UQ); Wir verkörpern die Werte, die wir direkt durch diese Klasse abfragen müssen. Sehr objektorientiert.
Einige Projektteams haben einige seltsame Vorschriften, die SQL -Anweisungen nicht im Code erscheinen dürfen. Wenn dies eine Spezifikation ist, werden alle von mir gesehenen Codes unserer Firma nicht qualifiziert. Viel Stringspleißen in der Tasse lässt es deprimiert aussehen. Es ist wirklich schwer, vorhandenen Projekten verletzt zu werden.
SQL -Anweisungen sind im Code nicht zulässig. Dies ist ein guter Vorschlag, aber es hängt von dieser Gelegenheit ab. Schauen wir uns an, wie Hibernate HQL in Mapping -Dateien konfiguriert.
Schauen Sie sich die Konfigurationsdatei direkt an:
<query name = "queryByName"> <! [CDATA [von Benutzer usr wobei usr.name =: name]]> </query>
Wir haben ein solches Tag hinzugefügt, das anzeigt, dass es sich um eine HQL -Anweisung handelt.
Wenn wir diese Anweisung erhalten müssen, müssen wir dem Code nur einen Satz hinzufügen:
Query query = session.getNamedQuery ("queryByName"); Auf diese Weise wird die HQL -Anweisung erhalten.
HQL kann auch mit Kombinationen in SQL wie dem inneren Join, dem linken äußeren Join, dem rechten äußeren Join, vollem Join, abfragt werden.
Schauen wir uns ihren Gebrauch an:
Schauen wir uns zuerst die Entity -Klasse an, was wir in unseren Tests verwenden müssen:
öffentliche Klasse Tuser implementiert serialisierbar {private statische endgültige long serialversionuid = 1l; private int id; privates int Alter; privater Zeichenfolge Name; private set <adresse> adresses = new Hashset <adresse> (); // GET/SET -Methode weglassen} öffentliche Klasse -Adresse implementiert serialisierbar {private statische endgültige long serialversionuid = 1l; private int id; private String -Adresse; privater Touser -Benutzer; // Get/Set -Methode auslassen} Schauen wir uns die Zuordnungsdatei an:
<hibernate-mapping package = "org.hiberNate.tutorial name = "Alter" type = "java.lang.Ineger" column = "älter"/> <set name = "adresses" cascade = "all" table = "t_address" inverse = "true"> <key column = "user_id"/> <eins-zu-Many/> </set> </class> </hibernate-mapping> <hibernate-mapping-mapping package = "org.hiberNate.tutorial type = "java.lang.String"/> <viele zu eins name = "user" column = "user_id" not-null = "true"> </viele zu-eins> </class> </hibernate-mapping>
Sie müssen nur den entsprechenden Paketnamen ändern.
Lassen Sie uns formelle Tests durchführen:
Schauen wir uns vor dem Testen die Daten in der Tabelle an:
Die Daten der T_Address -Tabelle sind wie folgt:
Die T_USER -Tabellendaten sind wie folgt:
1) Schauen wir uns zunächst die innere Verbindung an, die von Inner Join Fetch in HQL abgerufen wird. Beachten Sie, dass die Bedeutung des Abholens hier darin besteht, die erforderlichen Daten abzurufen. Wenn nicht das Abrufen verwendet wird, sind die von uns abgerufenen Daten vom Objekt -Datentyp.
Schauen wir uns zuerst an
von Tuser USR Inner You
Wenn wir es ausführen, sehen wir, dass der Hibernate -Ausgang lautet:
Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.id as id0__ from t_user tuser0_ inner join t_address adresses1_ auf tuser0_.id = adresses1_.user_id
Wir können die Ergebnisse sehen, wenn wir in MySQL ausgeführt werden:
Wir können sehen, dass Hibernate es in eine innere Join -Erklärung umwandelt und die Adresse herausfindet.
Wir sehen, dass das Ergebnis keine Aufzeichnung von Shun4 enthält, da es nicht die entsprechende Adresse und Aufzeichnung enthält.
Wenn wir inneren Join anstelle von Fetch verwenden, lautet die Aussage, die sie druckt:
Hibernate: Wählen Sie tuser0_.id als id1_0_, adresses1_.id as id0_1_, tuser0_.name als name1_0_, tuser0_.age ASAGE1_0_, adresses1_.adDress as adress0_1_, adressive tuser0_.id = adresses1_.user_id
Es scheint, dass die Aussage nicht anders ist, aber wenn wir sie herausfinden, erhält sie ein Objekt [] Array -Typ, sodass Sie auf diese Analyse achten müssen.
Wenn wir Fetch nicht verwenden, sondern nur innere Verbindung, müssen wir es so analysieren:
Query query = session.createquery ("von Tuser usr Inner Inner Join usr.addresses"); Listlist = query.list (); Iterator iter = list.Iterator (); while (iter.hasnext ()) {Object [] results = (Object []) iter.next (); für (int i = 0; i <results.length; i ++) {System.out.println (Ergebnisse [i]); }} Wir sehen das Druckergebnis:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutororial.domain6.tuser@787d6a org.hibernate.tutor.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain6.domain org.hibernate.tutorial.domain6.tuser@1326484 org.hiNNNATE.TUTORIAL.DOMAIN6.ADDRESS@16546EF
Jedes seiner Ergebnisse ist das entsprechende Objekt.
2) Linkes äußeres Join entspricht der linken Verbindung von SQL. Schauen wir uns das Beispiel direkt an:
Von Tuser Usr links Outer Join Fetch usr.adresses
Wenn wir die obige Aussage ausführen, druckt Hibernate aus:
Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.id as id0__ from t_user tuser0_ left outer Treten Sie T_Address adresses1_ auf tuser0_.id = adresses1_.user_id an
Wir haben es in MySQL überprüft und gesehen:
Wir sehen, dass Shun4 zwar keine entsprechende Adresse hat, es immer noch herausgefunden wird. Der linke äußere Join bezieht sich darauf, alle Datensätze in der linken Tabelle herauszufinden.
Ich werde nicht über die Situation sprechen, ohne hier zu holen.
3) Schauen wir uns als nächstes einen Blick auf die richtige äußere Verbindung. Nach dem Namen zu urteilen, muss es mit der linken äußeren Verbindung zusammenhängen. Wir können es deutlich sehen, indem wir uns die Beispiele direkt ansehen.
Vom Tuser USR Right Outer Join Fetch usr.adresses
Wir führen es aus und erhalten die Ausgabe der Ergebnisanweisung von Hibernate::
Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.id as id0__ from t_user tuser0_ right outer Treten Sie T_Address adresses1_ auf tuser0_.id = adresses1_.user_id anWir können die Ergebnisse nach der Ausführung in MySQL sehen:
Hier können wir sehen, dass die Adresse Test4 ist und nicht den entsprechenden Benutzer entspricht, der ihm entspricht, aber sie wird immer noch herausgefunden. Der rechte äußere Join bezieht sich darauf, alle Datensätze in der richtigen Tabelle zu finden.
Die Situation des Abrufens ist wie oben. Wenn Sie nicht verstehen, können Sie sich den inneren Join -Fetch ansehen.