Frage

Ich verwende den folgenden Code, um eine Datenbank von meinem jsp abfragen, aber ich würde gerne mehr darüber wissen, was hinter den Kulissen passiert.

Das sind meine zwei primären Fragen.

Ist das Tag Zugang der ResultSet direkt oder ist das Abfrageergebnis in einer Datenstruktur im Speicher abgelegt werden?

Wenn die Verbindung geschlossen?

<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>

<sql:query var="query" dataSource="${ds}" sql="${listQuery}"></sql:query>
<c:forEach var="row" items="${query.rows}" begin="0">
    ${row.data }
    ${row.more_data }
</c:forEach>

Hinweis: Ich habe immer gegen laufende Abfragen in den jsp, aber meine Ergebnismenge zu groß ist im Speicher zwischen meinem Handeln und meinem jsp. Diese Tag-Bibliothek sieht aus wie die einfachste Lösung.

War es hilfreich?

Lösung

Beobachtungen auf der Grundlage der Quelle für org.apache.taglibs.standard.tag.common.sql.QueryTagSupport

Die taglib quert durch die ResultSet und stellt alle Daten in Arrays, Karten und Listen. Also, alles in den Speicher geladen, bevor Sie beginnen sogar Looping.

Die Verbindung geöffnet wird, wenn die Abfrage Start-Tag angetroffen wird (doStartTag Methode). Die Ergebnisse werden abgerufen, wenn die Abfrage End-Tag (doEndTag Methode) angetroffen wird. Die Verbindung wird im doFinally Verfahren geschlossen.

Es ist ein Punkt gebracht, es ist absolut schrecklich.

Andere Tipps

Das Wichtigste hier ist diese: javax.servlet.jsp.jstl.sql.Result

Das ist, was JSTL verwendet als Ergebnis einer SQL-Abfrage. Wenn Sie an der Schnittstelle aussehen, hat es diese Methode:

public java.util.SortedMap [] getRows ()

c: forEach "weiß" über javax.servlet.jsp.jstl.sql.Result, da Ergebnis ist nichts anderes, dass forEach kennt (Collections, Arrays, Iteratoren, etc.)

.

Also, all das bedeutet, dass die SQL-Abfrage die gesamte Ergebnismenge in den RAM-Speicher saugen wird.

Wenn Sie Ihre Abfrage in die JSP bewegen, weil Sie nicht die gesamte Ergebnismenge in eine Sammlung laden wollten, dann ist es nicht, wie der SQL-Tag aussehen wird für Dich das Problem lösen.

In Wahrheit sollten Sie Werteliste Muster suchen.

Aber eine „einfache“ Lösung für Ihr Problem wäre eine benutzerdefinierte Iterator zu erstellen, die über Ihre ResultSet „wissen“. Dieser wickelt eine Ergebnismenge und schließt alles, wenn es eine Ausnahme oder wenn das Ergebnis verläuft trifft (wie wäre es in einem forEach). Art einer Zweck Sache.

public class ResultSetIterator implements Iterator {

Connection con;
Statement s;
ResultSet rs;
Object curObject;
boolean closed;

public ResultSetIterator(Connection con, Statement s, ResultSet rs) {
    this.con = con;
    this.s = s;
    this.rs = rs;
    closed = false;
}

public boolean hasNext() {
    advance();
    return curObject != null;
}

public Object next() {
    advance();
    if (curObject == null) {
        throw new NoSuchElementException();
    } else {
        Object result = curObject;
        curObject = null;
        return result;
    }
}

public void remove() {
    throw new UnsupportedOperationException("Not supported yet.");
}

private void advance() {
    if (closed) {
        curObject = null;
        return;
    }
    if (curObject == null) {
        try {
            if (rs.next()) {
                curObject = bindObject(rs);
            }
        } catch (SQLException ex) {
            shutDown();
            throw new RuntimeException(ex);
        }
    }
    if (curObject == null) {
        // Still no object, must be at the end of the result set
        shutDown();
    }
}

protected Object bindObject(ResultSet rs) throws SQLException {
    // Bind result set row to an object, replace or override this method
    String name = rs.getString(1);
    return name;
}

public void shutDown() {
    closed = true;
    try {
        rs.close();
    } catch (SQLException ex) {
        // Ignored
    }
    try {
        s.close();
    } catch (SQLException ex) {
        // Ignored
    }
    try {
        con.close();
    } catch (SQLException ex) {
        // Ignored
    }
}

}

Das ist natürlich nicht getestet. Aber da JSTLs forEach kann mit einem Iterator arbeiten, ist es das einfachste Objekt, das Sie wirklich, um es passieren könnte. Dies wird verhindern, dass Sie die gesamte Ergebnismenge in dem Speicher geladen werden. (Als interessantes beiseite, es ist bemerkenswert, wie fast, aber nicht ganz, ganz im Gegensatz zu Iterator ein Result Verhalten.)

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