Manchmal geben Anwendungsabfragen an eine Datenbank eine große Anzahl von Zeilen zurück. Obwohl abgerufene Daten innerhalb des ResultSet zwischengespeichert werden Objekt, ist es oft zu groß, um damit zu arbeiten. Daher müssen wir in der Lage sein, sie in verschiedenen Datensätzen zu filtern, um die sichtbaren Zeilen einzuschränken. Dieser Artikel befasst sich mit der Beschreibung des Filteraspekts von JDBC RowSet mit entsprechenden Beispielen.
Ein Überblick über RowSet
RowSet ist eine Schnittstelle, die das JDBC-API für JavaBeans-Komponentenmodell ergänzt. Es bietet eine Reihe von Eigenschaften, mit denen seine Instanz so konfiguriert werden kann, dass sie eine Verbindung zu einer JDBC-Datenquelle herstellt. Ein RowSet Die Instanz wird hauptsächlich zum Abrufen von Daten aus der Datenquelle verwendet. Die Setter-Methoden dieser Schnittstelle werden verwendet, um die Parameter der Befehlseigenschaft einer SQL-Abfrage zu füllen, die dann zum Abrufen von Datensätzen aus der relationalen Datenbank verwendet wird. Weil RowSet hält sich an das JavaBean-Komponentenmodell und unterstützt JavaBean-Ereignisse. Diese Ereignisse werden verwendet, um andere Komponenten über Ereignisse zu benachrichtigen, z. B. eine Wertänderung in einem Rowset. Da das RowSet Die Schnittstelle ist als Schicht über dem JDBC-Treiber konzipiert und offen für benutzerdefinierte Implementierungen. Diese Freiheit versetzt den Anbieter in die Lage, seine eigene feinabgestimmte Wirkung herzustellen und sie mit dem JDBC-Produkt auszuliefern.
Das FilteredRowSet
Das FilteredRowSet ist eine Schnittstellenerweiterung des RowSet Familie. Es gibt eine Referenzimplementierung dieser Schnittstelle namens FilteredRowSetImpl Klasse. Um eine benutzerdefinierte Implementierung von FilteredRowSet bereitzustellen -Schnittstelle kann man entweder das FilteredRowSetImpl erweitern Klasse oder verwenden Sie das FilteredRowSet Schnittstelle nach Ihren Anforderungen. In einigen Fällen müssen wir eine Art Filterung auf den Inhalt dieses RowSet anwenden holt. Eine einfache mögliche Lösung besteht darin, eine Abfragesprache für alle RowSets bereitzustellen Implementierungen. Dies ist jedoch kein praktikabler Ansatz, da RowSet ist mit der Idee eines entkoppelten Leichtbauteils aufgebaut. Dies würde das Objekt schwer machen und gegen sein Konstruktionsprinzip verstoßen. Wir brauchen einen Ansatz, der den Bedarf anspricht, aber keine schwergewichtige Abfragesprache zusammen mit der Verarbeitungslogik der Filterung einfügt. Das JDBC-FilteredRowSet Standardimplementierung erweitert RowSet über die Unterschnittstellen wie CachedRowSet und WebRowSet bzw. Das FilteredRowSet kann den Cursor durch den Satz von geschützten Cursor-Manipulationsmethoden manipulieren, die von CachedRowSet bereitgestellt werden Schnittstelle. Diese Methoden können je nach Bedarf überschrieben werden und helfen beim Filtern von RowSet Inhalt.
Ein kurzes Beispiel
Hier ist ein Beispiel, um zu veranschaulichen, wie FilteredRowSet wird verwendet, um den Inhalt zu speichern, der von der an die Datenbank gesendeten Abfrage zurückgegeben wird. Das Ergebnis der Abfrage wird gemäß der auf FilteredRowset angewendeten Konfiguration gefiltert Implementierung. Dies definiert den sichtbaren Inhalt oder die Zeilen, an denen wir aus dem von der Abfrage zurückgegebenen Ergebnis interessiert sind. Im folgenden Beispiel haben wir eine Filterklasse namens SimpleFilter erstellt . Diese Klasse definiert in unserem Fall die benutzerdefinierte Implementierung von FilteredRowSet . Wir haben diesen Filter dann auf das von der Datenbankabfrage zurückgegebene Ergebnis angewendet. Filtern bedeutet, die Anzahl der sichtbaren Zeilen zu begrenzen. Daher begrenzen wir hier die Anzahl der Buchinformationsdatensätze gemäß dem ausgewählten Autorennamen, der bereitgestellt wird.
Zum Anfassen folgen die Datenbanktabellen, die mit dem kommenden Java-Code verwendet werden.
Abbildung 1: Datenbanktabelle, Buch
Abbildung 2: Datenbanktabelle, Autor
Abbildung 3: Datenbanktabelle, book_author
Der SimpleFilter Klasse implementiert das Prädikat evaluieren Methoden zur Implementierung unseres benutzerdefinierten Filters.
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; } }
Diese Klasse wird verwendet, um das SimpleRowSet auszuführen Filterklasse. Beachten Sie, wie wir FilteredRowSet verwendet haben um Daten in der Anwendung zu filtern. Die Verarbeitung erfolgt auf Anwendungsebene und nicht auf SQL-Datenbankebene. Als Ergebnis können wir eine Reihe von Filtern implementieren und sie auf dieselbe Ergebnismenge anwenden, um das gewünschte Ergebnis zu erhalten. Dies verbessert die Leistung, da wir nicht mehrere Abfragen an die Datenbank senden müssen, um ein geändertes Ergebnis zu erhalten. Stattdessen können wir mehrere Filter auf das Abfrageergebnis anwenden, das einmal auf die Datenbank abgefeuert wurde. Die Bewerbung hat zwei wichtige Phasen:
- Wir erstellen einen Filter, der die Kriterien zum Filtern der Daten festlegt. Dies geschieht durch die Implementierung des Prädikats Schnittstelle. Es kann mehrere Konstruktoren geben, die unterschiedliche Argumentsätze akzeptieren. Außerdem kann der Filter ein Array von evaluate() enthalten Methoden, die auch unterschiedliche Sätze von Argumenten mit ihrem eigenen Satz von Implementierungen akzeptieren.
- Das FilteredRowSet Klasse muss instanziiert werden, um den gewünschten Effekt zu erzielen, was wir hier mit applyFilter() getan haben Methode. Das FilteredRowSet verwendet die von uns bereitgestellte benutzerdefinierte Filterklasse, um die anzuzeigenden Datensätze zu bestimmen.
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(); } } }
Ausgabe
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
Schlussfolgerung
Das Arbeiten mit einer großen Anzahl von Zeilen, die von einer Abfrage zurückgegeben werden, hat viele Probleme. Zum einen belegen abgerufene Daten Speicher.
Es hilft immer, sie je nach Bedarf und Relevanz einzuschränken. Mit RowSet , können wir diese ohne zusätzliche Datenbankabfragen nach einem Kriterium filtern. Dies macht es einfacher, mit Datenbankzeilen zu arbeiten, und nutzt die Effizienz des Codes.