2009-03-13 5 views
15

Sto facendo una query per recuperare una grande quantità di ID (interi). Invece di scorrere milioni di volte attraverso il ResultSet e copiare tutto uno per uno in un ArrayList, c'è un modo per recuperare semplicemente tutto come ArrayList?Come posso recuperare un ResultSet JDBC come ArrayList?

Capisco che ResultSet debba essere iterato perché l'implementazione sottostante potrebbe essere il caching, ma nella mia situazione ho solo bisogno di tutti gli ID immediatamente. So che posso impostare il FetchSize su un numero elevato, ma poi devo ancora recuperare gli ID uno per uno.

Precisazione: il motivo per cui voglio farlo è la prestazione. Il profiling mi mostra che eseguire ResultSet.next(), ResultSet.getInt() e ArrayList.add() milioni di volte richiede un po 'di tempo. Immagino che il database (sto usando H2, che è scritto in Java) probabilmente abbia l'array o l'elenco da qualche parte in memoria, quindi sto cercando un modo per copiarlo direttamente invece che attraverso l'interfaccia iterativa ResultSet .

+1

Probabilmente occuparsi di milioni di interi richiede molto tempo. Vuoi invece un int [] o primitivo come un elenco? Probabilmente non è implementato direttamente come int/List a causa di aggiornamenti e tableness generale. –

+0

int [] o Elenco sono entrambi a posto. Fondamentalmente sto solo cercando un modo per dire al database: dimentica il caching/lazy loading/etc., Dammi i dati il ​​più velocemente possibile :) – Deckard

+1

Avere un profilo e vedere dove si trova il problema. (Oracle ha ottenuto i metodi di array di colonne sul suo ResultSet, IIRC. Non che ciò sia importante per H2.) –

risposta

6

Inserire il codice in un metodo. E 'molto semplice da chiamare i metodi ...

Fuori della parte superiore della mia testa:

public static List<Integer> readInts(
    PreparedStatement statement 
) throws SQLException { 
    ResultSet results = statement.executeQuery(); 
    try { 
     assert results.getMetaData().getColumnCount() == 1; 

     List<Integer> ints = new ArrayList<Integer>(); 
     while (results.next()) { 
      ints.add(Integer.valueOf(results.getInt(1))); 
     } 
     return ints; 
    } finally { 
     results.close(); 
    } 
} 

Poi, proprio come lo chiamano:

List<Integer> ids = readInts(myStatemnet); 

Fatto.

+2

questo non aiuta le prestazioni si sta ancora eseguendo il ciclo dei dati. Credo che voglia solo scaricarlo. –

+1

come si "scaricherà" senza eseguire il looping dei dati? (L'ultimo paragrafo della domanda non era nell'originale, btw.) –

17

Utilizzando la libreria Apache DbUtils è possibile restituire facilmente un ResultSet come elenco di mappe.

public List query(String query) { 
    List result = null; 
    try { 
     QueryRunner qrun = new QueryRunner(); 
     result = (List) qrun.query(connection, query, new MapListHandler()); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
    return result; 
} 
+0

Questo non supererà la JDBC stessa? D'accordo, sembra più conveniente, ma certamente, non è più veloce ...? –

+0

DbUtils è una libreria di supporto, quindi stai ancora utilizzando JDBC. Dai un'occhiata al loro sito per alcuni dei vantaggi dell'utilizzo di DbUtils. http://commons.apache.org/dbutils/ – Mark

+0

Capisco, ma l'OP sembra aver cambiato la domanda dopo aver risposto. Stavano cercando un modo per aggirare l'API JDBC, al fine di migliorare le prestazioni ... –

5

Se il problema è scarso rendimento, sintonizzare la dichiarazione prima di eseguirlo con

java.sql.Statement.setFetchSize(int) 

Esperimento con 100, 1000, 10000, .. Questo eviterà di andata e ritorno non necessarie, che possono essere la causa di la lentezza che hai menzionato.

Inoltre, ArrayList.add() potrebbe essere lento se deve ridimensionare l'array interno più volte, in quanto crea una nuova matrice e copia tutti i dati lì. Prova invece LinkedList.

+0

Se si conosce la dimensione del recupero che si intende utilizzare, è possibile dichiarare nel costruttore ArrayList anche la dimensione iniziale dell'array interno con la stessa quantità. –

+1

@Daddy Da quello che ho capito, l'autore della domanda stava aggiungendo tutti gli ID restituiti a una singola lista. Ciò significa che il tuo suggerimento in realtà non aiuta a meno che non crei un array con le dimensioni complete del set di risultati, non solo il file di recupero. – Antonio

+1

@Deckard, questa domanda non ha ancora accettato risposta, hai risolto questo problema? – malatesh