Terkadang, kueri aplikasi ke database mengembalikan sejumlah besar baris. Meskipun data yang diambil di-cache di dalam ResultSet objek, seringkali terlalu besar untuk bekerja dengan mereka. Akibatnya, kita harus dapat memfilternya dalam kumpulan data yang berbeda untuk membatasi baris yang terlihat. Artikel ini menjelaskan tentang aspek pemfilteran JDBC RowSet dengan contoh yang sesuai.
Ikhtisar RowSet
RowSet adalah antarmuka yang melengkapi JDBC API untuk model komponen JavaBeans. Ini menyediakan satu set properti yang memungkinkan instansnya dikonfigurasi untuk terhubung ke sumber data JDBC. Sebuah RowSet instance terutama digunakan untuk mengambil data dari sumber data. Metode penyetel antarmuka ini digunakan untuk mengisi parameter properti perintah dari kueri SQL, yang kemudian digunakan untuk mengambil catatan dari database relasional. Karena RowSet mematuhi model komponen JavaBean, mendukung acara JavaBean. Peristiwa ini digunakan untuk memberi tahu komponen lain tentang peristiwa, seperti perubahan nilai pada rowset. Karena RowSet antarmuka dirancang sebagai lapisan di atas driver JDBC, terbuka untuk implementasi khusus. Kebebasan ini memberdayakan vendor untuk membuat efek mereka sendiri yang telah disesuaikan dan mengirimkannya dengan produk JDBC.
FilteredRowSet
FilteredRowSet adalah ekstensi antarmuka RowSet keluarga. Ada implementasi referensi dari antarmuka ini, yang disebut FilteredRowSetImpl kelas. Untuk menyediakan implementasi kustom FilteredRowSet antarmuka, seseorang dapat memperluas FilteredRowSetImpl kelas atau gunakan FilteredRowSet antarmuka sesuai kebutuhan Anda. Pada beberapa kesempatan, kita perlu menerapkan beberapa bentuk pemfilteran pada konten yang RowSet mengambil. Solusi sederhana yang mungkin adalah menyediakan bahasa kueri untuk semua RowSet implementasi. Tapi kemudian, ini bukan pendekatan yang layak karena RowSet dibangun dengan ide komponen ringan yang terputus. Ini akan membuat objek menjadi berat dan bertentangan dengan prinsip desainnya. Kami membutuhkan pendekatan yang menjawab kebutuhan namun tidak memasukkan bahasa kueri kelas berat bersama dengan logika pemrosesan pemfilteran. JDBC FilteredRowSet implementasi standar memperluas RowSet melalui subinterface seperti CachedRowSet dan WebRowSet masing-masing. FilteredRowSet dapat memanipulasi kursor melalui serangkaian metode manipulasi kursor yang dilindungi yang disediakan oleh CachedRowSet antarmuka. Metode ini dapat diganti sesuai kebutuhan dan bantuan saat memfilter RowSet konten.
Contoh Singkat
Berikut adalah contoh untuk menggambarkan bagaimana FilteredRowSet digunakan untuk menyimpan konten yang dikembalikan oleh kueri yang dikirim ke database. Hasil kueri difilter menurut konfigurasi yang diterapkan ke FilteredRowset penerapan. Ini mendefinisikan konten yang terlihat atau baris yang kami minati dari hasil yang dikembalikan oleh kueri. Dalam contoh berikut, kami telah membuat kelas filter yang disebut SimpleFilter . Kelas ini, dalam kasus kami, mendefinisikan implementasi kustom dari FilteredRowSet . Kami kemudian menerapkan filter ini pada hasil yang dikembalikan dari kueri database. Pemfilteran berarti membatasi jumlah baris yang akan terlihat. Oleh karena itu, di sini kami akan membatasi jumlah catatan informasi buku sesuai dengan nama penulis terpilih yang diberikan.
Sebagai contoh, berikut adalah tabel database yang digunakan dengan kode Java yang akan datang.
Gambar 1: Tabel basis data, buku
Gambar 2: Tabel basis data, penulis
Gambar 3: Tabel basis data, penulis_buku
Filter Sederhana kelas mengimplementasikan Predikat metode evaluasi untuk menerapkan filter khusus kami.
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; } }
Kelas ini digunakan untuk mengeksekusi SimpleRowSet kelas filter. Perhatikan bagaimana kami menggunakan FilteredRowSet untuk menyaring data dalam aplikasi. Pemrosesan terjadi di tingkat aplikasi daripada di tingkat database SQL. Akibatnya, kita dapat menerapkan serangkaian filter dan menerapkannya pada kumpulan hasil yang sama untuk mendapatkan hasil yang diinginkan. Ini meningkatkan kinerja karena kami tidak perlu mengaktifkan beberapa kueri ke database untuk mendapatkan hasil yang dimodifikasi. Sebagai gantinya, kita dapat menerapkan beberapa pemfilteran pada hasil kueri yang diaktifkan sekali ke database. Aplikasi ini memiliki dua fase penting:
- Kami membuat filter yang menetapkan kriteria untuk memfilter data. Ini dilakukan dengan menerapkan Predikat antarmuka. Mungkin ada beberapa konstruktor yang menerima serangkaian argumen yang berbeda. Selain itu, filter mungkin berisi larik evaluate() metode juga menerima serangkaian argumen yang berbeda dengan rangkaian implementasinya sendiri yang berbeda.
- FilteredRowSet kelas harus dipakai untuk mendapatkan efek yang diinginkan, sesuatu yang telah kita lakukan di sini dengan applyFilter() metode. FilteredRowSet menggunakan kelas filter khusus yang telah kami sediakan untuk menentukan catatan yang akan dilihat.
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(); } } }
Keluaran
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
Kesimpulan
Bekerja dengan sejumlah besar baris yang dikembalikan dari kueri memiliki banyak masalah. Pertama, data yang diambil menempati memori.
Itu selalu membantu untuk membatasi mereka sesuai dengan kebutuhan dan relevansi. Dengan RowSet , kami dapat memfilternya menurut kriteria tanpa membuat permintaan basis data tambahan. Ini membuatnya lebih mudah dikelola untuk bekerja dengan baris database dan meningkatkan efisiensi kode.