A volte, le query dell'applicazione a un database restituiscono un numero elevato di righe. Sebbene i dati recuperati siano memorizzati nella cache all'interno di ResultSet oggetto, spesso è troppo grande per lavorarci. Di conseguenza, dobbiamo essere in grado di filtrarli in diversi set di dati per limitare le righe visibili. Questo articolo approfondisce la descrizione dell'aspetto del filtro di JDBC RowSet con esempi appropriati.
Una panoramica di RowSet
Set di righe è un'interfaccia che integra l'API JDBC per il modello del componente JavaBeans. Fornisce una serie di proprietà che consentono di configurare la sua istanza per la connessione a un'origine dati JDBC. Un insieme di righe istanza viene utilizzata principalmente per recuperare i dati dall'origine dati. I metodi setter di questa interfaccia vengono utilizzati per popolare i parametri della proprietà del comando di una query SQL, che viene quindi utilizzata per recuperare i record dal database relazionale. Perché RowSet aderisce al modello del componente JavaBean, supporta gli eventi JavaBean. Questi eventi vengono utilizzati per notificare ad altri componenti eventi, ad esempio una modifica del valore su un set di righe. Perché il RowSet l'interfaccia è progettata come un livello sopra il driver JDBC, è aperta all'implementazione personalizzata. Questa libertà consente al venditore di fabbricare la propria realizzazione ottimizzata e spedirla con il prodotto JDBC.
Il FilteredRowSet
Il FilteredRowSet è un'estensione dell'interfaccia di RowSet famiglia. Esiste un'implementazione di riferimento di questa interfaccia, chiamata FilteredRowSetImpl classe. Per fornire un'implementazione personalizzata di FilteredRowSet interfaccia, si può estendere il FilteredRowSetImpl classe o utilizzare il FilteredRowSet interfaccia secondo il vostro requisito. In alcune occasioni, è necessario applicare una qualche forma di filtro al contenuto che RowSet recupera. Una semplice soluzione possibile è fornire un linguaggio di query per tutti i RowSet implementazioni. Ma questo non è un approccio praticabile perché RowSet è costruito con l'idea di un componente leggero scollegato. Ciò renderebbe l'oggetto pesante e andrebbe contro il suo principio di progettazione. Abbiamo bisogno di un approccio che risponda alla necessità ma non inietti un linguaggio di query pesante insieme alla logica di elaborazione del filtro. Il FilteredRowSet di JDBC l'implementazione standard estende RowSet attraverso le sottointerfacce come CachedRowSet e WebRowSet rispettivamente. Il FilteredRowSet può manipolare il cursore attraverso l'insieme di metodi protetti di manipolazione del cursore forniti da CachedRowSet interfaccia. Questi metodi possono essere ignorati in base ai requisiti e aiutano durante il filtraggio di RowSet contenuto.
Un rapido esempio
Ecco un esempio per illustrare come FilteredRowSet viene utilizzato per archiviare i contenuti restituiti dalla query avviata al database. Il risultato della query viene filtrato in base alla configurazione applicata al FilteredRowset implementazione. Questo definisce il contenuto visibile o le righe che ci interessano dal risultato restituito dalla query. Nell'esempio seguente, abbiamo creato una classe di filtri chiamata SimpleFilter . Questa classe, nel nostro caso, definisce l'implementazione personalizzata di FilteredRowSet . Abbiamo quindi applicato questo filtro sul risultato restituito dalla query del database. Filtraggio significa limitare il numero di righe che saranno visibili. Pertanto, qui limiteremo il numero di record di informazioni sui libri in base al nome dell'autore selezionato fornito.
Di seguito sono riportate le tabelle del database utilizzate con il prossimo codice Java.
Figura 1: Tabella database, libro
Figura 2: Tabella del database, autore
Figura 3: Tabella del database, autore_libro
Il Filtro semplice la classe implementa il Predicato 's valuta i metodi per implementare il nostro filtro personalizzato.
package org.mano.example; import javax.sql.RowSet; import javax.sql.rowset.Predicate; import java.sql.SQLException; public class SimpleFilter implements Predicate { private String[] authors; private String colname = null; private int colno = -1; public SimpleFilter(String[] authors, String colname) { this.authors = authors; this.colno = -1; this.colname = colname; } public SimpleFilter(String[] authors, int colno) { this.authors = authors; this.colno = colno; this.colname = null; } @Override public Boolean evaluate(Object value, String colName) { if (colName.equalsIgnoreCase(this.colname)) { for (String author : this.authors) { if (author.equalsIgnoreCase((String)value)) { return true; } } } return false; } @Override public Boolean evaluate(Object value, int colNumber) { if (colNumber == this.colno) { for (String author : this.authors) if (author.equalsIgnoreCase((String)value)) { return true; } } } return false } @Override public Boolean evaluate(RowSet rs) { if (rs == null) return false; try { for (int i=0;i<authors.length;i++) { String al = null; if (this.colno> 0) { al = (String)rs.getObject(this.colno); } else if (this.colname != null) { al = (String)rs.getObject(this.colname); } else { return false; } if (al.equalsIgnoreCase(authors[i])) { return true; } } } catch (SQLException e) { return false; } return false; } }
Questa classe viene utilizzata per eseguire SimpleRowSet classe di filtro. Nota come abbiamo utilizzato FilteredRowSet per filtrare i dati nell'applicazione. L'elaborazione avviene a livello di applicazione anziché a livello di database SQL. Di conseguenza, possiamo implementare una serie di filtri e applicarli sullo stesso set di risultati per ottenere il risultato desiderato. Ciò sfrutta le prestazioni perché non è necessario eseguire più query sul database per ottenere un risultato modificato. Invece, possiamo applicare più filtri sul risultato della query attivato una volta al database. L'applicazione ha due fasi importanti:
- Creiamo un filtro che stabilisce i criteri per filtrare i dati. Questo viene fatto implementando il Predicato interfaccia. Possono esserci più costruttori che accettano diversi set di argomenti. Inoltre, il filtro può contenere un array di evaluate() metodi che accettano anche diversi insiemi di argomenti con il proprio insieme distinto di implementazione.
- Il FilteredRowSet class deve essere istanziata per ottenere l'effetto desiderato, cosa che abbiamo fatto qui con applyFilter() metodo. Il FilteredRowSet utilizza la classe di filtro personalizzata che abbiamo fornito per determinare i record da visualizzare.
package org.mano.example; import com.sun.rowset.FilteredRowSetImpl; import javax.sql.RowSet; import javax.sql.rowset.FilteredRowSet; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class DemoApp { private static final String DB_URL = "jdbc:mysql://localhost:3306/my_lib"; private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String DB_USERNAME = "root"; private static final String DB_PASSWORD = "secret"; public static Connection conn = null; public static FilteredRowSet filteredRowSet = null; public static void main(String[] args) { try { Class.forName(DB_DRIVER); conn = DriverManager.getConnection(DB_URL, DB_USERNAME,DB_PASSWORD); System.out.println("Database connection successful."); applyFilter(); } catch (SQLException | ClassNotFoundException ex) { System.out.println(ex); } finally { if (conn != null) { try { conn.close(); catch (SQLException ex) { ex.printStackTrace(); } } if (filteredRowSet != null) { try { filteredRowSet.close(); } catch (SQLException ex) { ex.printStackTrace(); } } } } public static void applyFilter() { String[] arr = {"Donne", "Milton"}; SimpleFilter aFilter = new SimpleFilter(arr, 3); try { filteredRowSet = new FilteredRowSetImpl(); filteredRowSet.setCommand("SELECT title, f_name, l_name " + "FROM book_author BA, " + "author A, " + "book B " + "WHERE A.auth_id = BA.fk_author " + "AND B.book_id = BA.fk_book"); filteredRowSet.execute(conn); System.out.println ("--------------------------------------------"); System.out.println("Before applying any filter:"); System.out.println ("--------------------------------------------"); show(filteredRowSet); System.out.println ("--------------------------------------------"); System.out.println("After applying filter :"); System.out.println ("--------------------------------------------"); filteredRowSet.beforeFirst(); filteredRowSet.setFilter(aFilter); show(filteredRowSet); } catch (SQLException e) { e.printStackTrace(); } } public static void show(RowSet rs) { try { while (rs.next()) { System.out.println(rs.getString(1) + " / " + rs.getString(2) + " "+rs.getString(3)); } } catch (SQLException ex) { ex.printStackTrace(); } } }
Uscita
Database connection successful. -------------------------------------------- Before applying any filter: -------------------------------------------- Gulliver's Travels / Jonathan Swift ... Ill Pensoroso / John Milton Areopagitica / John Milton -------------------------------------------- After applying filter: -------------------------------------------- The Flea / John Donne Holy Sonnet / John Donne Paradise Lost / John Milton Paradise Regained / John Milton Ill Pensoroso / John Milton Areopagitica / John Milton
Conclusione
L'utilizzo di un numero elevato di righe restituite da una query presenta molti problemi. Per uno, i dati recuperati occupano memoria.
Aiuta sempre a limitarli in base alla necessità e alla pertinenza. Con Set di righe , possiamo filtrarli secondo un criterio senza fare richieste aggiuntive al database. Ciò rende più gestibile il lavoro con le righe del database e sfrutta l'efficienza del codice.