Frage

Die Umsetzung-Ergebnis-paging-in-hibernate-immer-total-number-of-rows Frage trigger eine andere Frage, die für mich über einige Umsetzung Sorge:

Jetzt wissen Sie, Sie haben, um die Wiederverwendung von teilen der HQL-Abfrage zu tun, die zählen, wie die Wiederverwendung effizient?

Die Unterschiede zwischen den zwei HQL-Abfragen sind:

  1. die Auswahl ist count(?), statt der pojo oder eine Eigenschaft (oder eine Liste)
  2. die holt sollte das nicht passieren, so dass einige Tabellen sollten nicht zusammen sein
  3. die order by sollte verschwinden

Gibt es andere Unterschiede?

Sie haben Codierung best practices " um dies zu erreichen Wiederverwendung effizient (betrifft:Bemühungen, Klarheit, Leistung)?

Beispiel für eine einfache HQL-Abfrage:

    select       a     from A a join fetch a.b b where a.id=66 order by a.name
    select count(a.id) from A a                  where a.id=66

AKTUALISIERT

Ich erhielt Antworten auf:

  • Verwendung Kriterien (aber wir verwenden HQL meistens)
  • Manipulation der Zeichenkette query (jeder stimmt es scheint kompliziert und nicht sehr sicher)
  • die Verpackung der Abfrage, die sich auf die Datenbank-Optimierung (aber es ist ein Gefühl, dies ist nicht sicher)

Ich war in der Hoffnung, jemand würde die Möglichkeit bieten, auf einem anderen Weg, mehr im Zusammenhang mit String-Verkettung.
Könnten wir bauen sowohl HQL-Abfragen, die Verwendung gemeinsamer Teile?

War es hilfreich?

Lösung

Nizza Frage. Hier ist, was ich in der Vergangenheit getan haben (viele Dinge, die Sie bereits erwähnt haben):

  1. Überprüfen Sie, ob SELECT Klausel vorhanden ist.
    1. Wenn es nicht, fügen Sie select count(*)
    2. Ansonsten prüfen, ob es hat DISTINCT oder Aggregatfunktionen in ihm. Wenn Sie ANTLR verwenden Ihre Abfrage zu analysieren, ist es möglich, um diejenigen zu arbeiten, aber es ist recht kompliziert. Du bist wahrscheinlich besser dran, nur das Ganze mit select count(*) from () gewickelt wird.
  2. Entfernen fetch all properties
  3. Entfernen fetch aus schließt sich, wenn Sie HQL als String sind Parsen. Wenn Sie wirklich die Abfrage mit ANTLR Parsen können Sie entfernen left join vollständig; es ist ziemlich chaotisch, alle möglichen Referenzen zu überprüfen.
  4. Entfernen order by
  5. Je nachdem, was Sie in 1.2 getan haben Sie entfernen müssen / einstellen group by / having.

Das Obige gilt für HQL, natürlich. Für Criteria-Abfragen sind Sie ziemlich begrenzt mit dem, was Sie tun können, weil sie sich nicht leicht manipulierbar verleihen. Wenn Sie irgendeine Art von Wrapper-Schicht oben auf Kriterien verwenden, werden Sie mit Äquivalent (begrenzten) Teilmenge von ANTLR Parsing Ergebnisse am Ende und konnte die meisten der oben in diesem Fall gelten.

Da Sie in der Regel auf würde halten der aktuellen Seite und die Gesamtzahl zu kompensieren, laufe ich in der Regel die eigentliche Abfrage mit vorgegebenen Grenzwert / Offset erste und nur die count(*) Abfrage ausführen, wenn Anzahl der Ergebnisse kehrt mehr oder gleich zu begrenzen und Offset-Null (in allen anderen Fällen ich habe entweder die count(*) laufen vor oder ich habe alle Ergebnisse zurückkamen sowieso). Dies ist ein optimistischer Ansatz im Hinblick auf die gleichzeitige Änderungen, natürlich.

Aktualisieren (auf der Hand organisierenden HQL)

ich nicht besonders mag diesen Ansatz. Wenn sie als benannte Abfrage zugeordnet ist, hat HQL den Vorteil, Build-Fehlerüberprüfung (na ja, Laufzeit technisch, weil Session gebaut werden muss, obwohl dies in der Regel während der Integrationstests ohnehin getan hat). Wenn zur Laufzeit generiert zur Laufzeit nicht :-) Optimierungen Leistung Doing entweder nicht ganz einfach ist.

Die gleiche Argumentation gilt für Kriterien, natürlich, aber es ist ein bisschen schwieriger, aufgrund gut definierte API vermasseln zu String-Verkettung gegenüber. Bau von zwei HQL-Abfragen parallel (ausgelagerten ein und „global count“ one) auch Doppelarbeit zu codieren führen (und möglicherweise mehr Fehler) oder zwingen Sie irgendeine Art von Wrapper-Schicht auf der Oberseite zu schreiben es für Sie zu tun. Beide Wege sind bei weitem nicht ideal. Und wenn Sie diesen Code von Client tun (wie in über API), wird das Problem noch schlimmer.

Ich habe tatsächlich legte ziemlich viel zu diesem Thema. Search API von Hibernate-generic-DAO scheint wie ein vernünftiger Kompromiss; gibt es mehr Details in meiner Antwort auf die oben verlinkten Frage.

Andere Tipps

Haben Sie versucht, die macht Ihre Absichten klar, um Winterschlaf zu halten, die durch die Einstellung einer Projektion, auf Ihr (SQL?)Kriterien?Ich habe überwiegend mit Hilfe von Kriterien, so dass ich nicht sicher bin, wie zutreffend dies ist, um Ihren Fall, aber ich habe mit

getSession().createCriteria(persistentClass).
setProjection(Projections.rowCount()).uniqueResult()

und lassen Hibernate Abbildung aus der caching / Wiederverwendung / smart stuff von selbst..Nicht wirklich sicher, wie viel intelligente Dinge, die es eigentlich nicht, wenn..Jemand darauf zu sagen?

Nun, ich bin nicht sicher, dies ist ein Best-Practice, aber ist mein-Praxis:)

Wenn ich als Abfrage so etwas wie:

select A.f1,A.f2,A.f3 from A, B where A.f2=B.f2 order by A.f1, B.f3

Und ich möchte nur wissen, wie viele Ergebnisse erhalten, ich ausführen:

select count(*) from ( select A.f1, ... order by A.f1, B.f3 )

Und dann das Ergebnis als Integer erhalten, ohne Kartierungsergebnisse in einer POJO.

Parse Ihre Abfrage für einige Teile zu entfernen, wie ‚order by‘ sehr kompliziert ist. Ein gutes RDBMS wird optimieren Ihre Anfrage für Sie.

Gute Frage.

In einer freihändig HQL Situation würde ich so etwas wie diese verwenden, aber dies ist nicht wieder verwendbar, da sie sehr spezifisch für die gegebenen Einheiten ist

Integer count = (Integer) session.createQuery("select count(*) from ....").uniqueResult();

dies einmal tun und anpassen Nummer durch entsprechend, bis Sie ab Seite.

Für Kriterien obwohl ich eine Probe wie folgt verwenden

final Criteria criteria = session.createCriteria(clazz);  
            List<Criterion> restrictions = factory.assemble(command.getFilter());
            for (Criterion restriction : restrictions)
                criteria.add(restriction);
            criteria.add(Restrictions.conjunction());
            if(this.projections != null)
                criteria.setProjection(factory.loadProjections(this.projections));
            criteria.addOrder(command.getDir().equals("ASC")?Order.asc(command.getSort()):Order.desc(command.getSort()));
            ScrollableResults scrollable = criteria.scroll(ScrollMode.SCROLL_INSENSITIVE);
            if(scrollable.last()){//returns true if there is a resultset
                genericDTO.setTotalCount(scrollable.getRowNumber() + 1);
                criteria.setFirstResult(command.getStart())
                        .setMaxResults(command.getLimit());
                genericDTO.setLineItems(Collections.unmodifiableList(criteria.list()));
            }
            scrollable.close();
            return genericDTO;

Aber das tut die Zählung jedes Mal durch ScrollableResults:last() aufrufen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top