Domanda

Sto usando il seguente codice per eseguire una query di un database da mio jsp, ma mi piacerebbe sapere di più su ciò che accade dietro le quinte.

Queste sono le mie due domande principali.

Il tag di accesso ResultSet direttamente, o è il risultato di una query archiviate in una datastructure in memoria?

Quando la connessione è chiusa?

<%@ 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>

Nota:Sono sempre stato contro l'esecuzione di query in jsp, ma il mio risultato troppo grande per memorizzare in memoria tra la mia azione e la mia jsp.Utilizzando questa libreria di tag sembra la soluzione più semplice.

È stato utile?

Soluzione

Osservazioni in base all'origine per org.apache.taglibs.standard.tag.comune.sql.QueryTagSupport

La taglib attraversa il ResultSet e mette tutti i dati in un array, Mappe ed Elenchi.Così, tutto ciò che viene caricato in memoria prima ancora di iniziare il ciclo.

La connessione viene aperto quando la query tag di inizio incontrato (doStartTag metodo).I risultati vengono recuperati quando la query fine tag incontrato (doEndTag metodo).La connessione è chiusa in doFinally metodo.

Un guscio di noce, è assolutamente orribile.

Altri suggerimenti

La cosa fondamentale è questo:javax.servlet.jsp.jstl.sql.Risultato

Che è quello che JSTL utilizza come il risultato di una Query SQL.Se si guarda l'interfaccia, ha questo metodo:

public java.util.SortedMap[] getRows()

c:forEach "sa" della javax.servlet.jsp.jstl.sql.Risultato, dal Risultato non è niente altro che forEach conosce (Collezioni, matrici, iteratori, ecc).

Quindi, tutto questo implica che la query SQL succhiare un intero set di RAM.

Se hai spostato la tua query in JSP perché non si desidera caricare un intero set di dati a una collezione, quindi non ha l'aspetto di SQL tag risolvere il problema per voi.

In verità si dovrebbe guardare Elenco di Valore del Modello.

Ma un "semplice" soluzione al tuo problema potrebbe essere quello di creare un custom Iteratore che "sa" della ResultSet.Questo avvolge di un set e chiude tutto se si verifica un'eccezione o se il risultato viene eseguito il suo corso (come si farebbe in un forEach).Tipo di scopo speciale cosa.

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
    }
}

}

Questo è, naturalmente, non testati.Ma dal momento che JSTLs forEach può lavorare con un Iteratore, è il più semplice oggetto non si poteva passare.Questo vi impedirà di carico intero set di dati in memoria.(Come un interessante a parte, è notevole come quasi, ma non del tutto, completamente, a differenza di un Iteratore di Risultati è il comportamento.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top