Saat mengambil daftar catatan melalui kueri, kita sering kali perlu menyimpannya dalam objek yang memungkinkan bolak-balik melintasi, memperbarui sesuai kebutuhan. Artikel ini mengilustrasikan teknik yang umum dibutuhkan dalam pemrograman database dengan kode eksplisit dan skenario contoh.
Tentang ResultSet
ResultSet adalah antarmuka yang didefinisikan dalam java.sql kemasan. Ini mewakili tabel data yang dikembalikan oleh Pernyataan obyek. Pernyataan objek digunakan untuk mengeksekusi query SQL ke database. Objek ResultSet mempertahankan kursor yang menunjuk ke catatan saat ini di tabel database. Hasilnya, ini dapat digunakan secara efektif untuk memposisikan pada baris yang berbeda, bolak-balik menggunakan first() , sebelumnya() , berikutnya() , dan terakhir() metode sesuai kebutuhan. Awalnya, ResultSet objek diposisikan di lokasi sebelum baris pertama. Inilah alasannya ResultSet traversal selalu dimulai sebagai berikut:
while(resultSet.next()) { // ... }
Perhatikan bahwa ResultSet objek diposisikan pada baris pertama dengan menjalankan berikutnya() metode saat memasuki loop, karena, seperti yang telah disebutkan, ResultSet objek awalnya terletak pada posisi tepat sebelum baris pertama. Jadi, itu harus diletakkan setidaknya di baris pertama, misalnya, untuk mendapatkan catatan yang valid. Ini dapat dianggap sebagai nilai -1 dalam posisi array yang ditunjuk oleh pointer/indeks. Itu harus terlebih dahulu dipindahkan ke setidaknya 0 lokasi untuk mendapatkan segala jenis nilai valid dari array.
Sekarang, seperti yang telah kami sebutkan, kami dapat menelusuri catatan dengan bantuan ResultSet obyek. Tapi, kemampuan ini tidak datang secara default. Perilaku default ResultSet objek adalah bahwa itu tidak dapat diperbarui dan kursor yang dimilikinya benar-benar bergerak dalam satu arah, hanya maju. Ini berarti bahwa kita dapat melakukan iterasi melalui record hanya sekali dan dalam arah maju saja. Namun, ada cara untuk membuatnya fleksibel sehingga ResultSet tidak hanya dapat diperbarui tetapi juga dapat digulir.
Kita akan melihatnya sebentar lagi di dua program terpisah.
Dapat digulir ResultSet
Pertama-tama mari kita buat ResultSet objek dapat digulir. Dapat digulir berarti sekali ResultSet objek telah dibuat, kita dapat melintasi catatan yang diambil ke segala arah, maju dan mundur, sesuka kita. Ini memberikan kemampuan untuk membaca catatan terakhir, catatan pertama, catatan berikutnya, dan catatan sebelumnya.
package org.mano.example; import java.sql.*; public class App { static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/employees"; static final String USER = "root"; static final String PASS = "secret"; static final String SQL = "SELECT * FROM employees ORDER BY first_name"; public static void main( String[] args ) { Connection connection = null; ResultSet rs = null; try { Class.forName(JDBC_DRIVER); connection = DriverManager.getConnection (DB_URL, USER, PASS); System.out.println("n1. Connection established"); }catch(Exception ex) { ex.printStackTrace(); } try (PreparedStatement pstmt = connection.prepareStatement(SQL, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);){ System.out.println("n2. Executing SQL query..."); rs = pstmt.executeQuery(); System.out.println("n3. ResultSet object created successfully."); System.out.println("n4. Now some RecordSet scrolling starts..."); rs.first(); show(rs); rs.last(); show(rs); rs.previous(); rs.previous(); show(rs); rs.next(); show(rs); System.out.println("nn5. That's all. RecordSet scrolling ends."); }catch(SQLException ex){ ex.printStackTrace(); }finally{ try { connection.close(); }catch(SQLException ex){ } } } public static void show(ResultSet rs) throws SQLException{ System.out.printf ("n--------------------------------"+ "-------------------------------------"); System.out.printf("n%7d | %10s | %10s | %s | %s | %s ",rs.getLong("emp_no"), rs.getString("first_name"), rs.getString("last_name"), rs.getDate("birth_date").toString(), rs.getDate("hire_date"), rs.getString("gender")); System.out.printf ("n---------------------------------"+ "------------------------------------"); } }
Keluaran
- Koneksi terjalin.
- Menjalankan kueri SQL…
- Objek ResultSet berhasil dibuat.
- Sekarang, beberapa pengguliran RecordSet dimulai...
------------------------------------------------------------- 497615 | Aamer | McDermid | 1954-11-18 | 1985-04-24 | M ------------------------------------------------------------- ------------------------------------------------------------- 484995 | Zvonko | Lakshmanan | 1964-11-04 | 1992-12-04 | M ------------------------------------------------------------- ------------------------------------------------------------- 482000 | Zvonko | Cannata | 1960-11-23 | 1986-08-13 | M ------------------------------------------------------------- ------------------------------------------------------------- 483497 | Zvonko | Pollacia | 1961-12-26 | 1985-08-01 | M -------------------------------------------------------------
- Itu saja. Pengguliran RecordSet berakhir.
Perhatikan bahwa ResultSet . yang dapat digulir objek adalah hasil dari eksekusi executeQuery() metode yang diperoleh melalui instance Pernyataan atau PreparedStatement . Jenis ResultSet objek yang ingin kita buat harus dideklarasikan secara eksplisit ke Pernyataan objek melalui konstanta jenis gulir yang ditentukan.
- ResultSet.TYPE_FORWARD_ONLY: Ini adalah tipe default.
- ResultSet.TYPE_SCROLL_INSENSITIVE: Mengaktifkan gerakan bolak-balik, tetapi tidak peka terhadap ResultSet pembaruan.
- ResultSet.TYPE_SCROLL_SENSITIVE: Mengaktifkan gerakan bolak-balik, tetapi peka terhadap ResultSet pembaruan.
Ada konstanta lain yang digunakan, seperti CONCUR_READ_ONLY , yang berarti ResultSet tidak dapat diperbarui. Ada konstanta lain, CONCUR_UPDATABLE , yang menandakan kebalikannya, artinya ResultSet dapat diperbarui.
Dapat diperbarui ResultSet
Membuat ResultSet . yang dapat diperbarui berarti bahwa catatan yang ditunjuknya tidak hanya dapat dilalui tetapi juga dapat diperbarui. Perubahan akan segera disimpan dalam database dan dicerminkan oleh ResultSet objek secara real time.
package org.mano.example; import java.sql.*; public class App { static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost:3306/employees"; static final String USER = "root"; static final String PASS = "secret"; static final String SQL = "SELECT * FROM employees WHERE emp_no = ?"; public static void main( String[] args ) { Connection connection = null; ResultSet rs = null; long emp_no = 484995; try { Class.forName(JDBC_DRIVER); connection = DriverManager.getConnection (DB_URL, USER, PASS); System.out.println("n1. Connection established"); }catch(Exception ex) { ex.printStackTrace(); } try(PreparedStatement pstmt = connection.prepareStatement(SQL, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);){ pstmt.setLong(1,emp_no); System.out.println("n2. Executing SQL query..."); rs = pstmt.executeQuery(); System.out.println("n3. ResultSet object created successfully."); while(rs.next()){ show(rs); String fname = rs.getString("first_name"); System.out.println("n4. Updating name "+fname+" to Subham"); rs.updateString("first_name", "Subham"); rs.updateRow(); } System.out.println("nn5. Record updated. See below."); rs.previous(); show(rs); }catch(SQLException ex){ ex.printStackTrace(); }finally{ try { rs.close(); connection.close(); }catch(SQLException ex){ } } } public static void show(ResultSet rs) throwsSQLException{ System.out.printf ("n--------------------------------"+ "-------------------------------------"); System.out.printf("n%7d | %10s | %10s | %s | %s | %s ",rs.getLong("emp_no"), rs.getString("first_name"), rs.getString("last_name"), rs.getDate("birth_date").toString(), rs.getDate("hire_date"), rs.getString("gender")); System.out.printf ("n---------------------------------"+ "------------------------------------"); } }
ResultSet . yang dapat diperbarui sangat berguna ketika kita ingin memperbarui nilai tertentu setelah melakukan beberapa perbandingan dengan melintasi bolak-balik melalui catatan yang diambil. Proses pembuatannya mirip dengan program sebelumnya, tetapi ResultSet konstanta yang digunakan di sini adalah TYPE_SCROLL_SENSITIVE dan CONCUR_UPDATABLE .
Kesimpulan
Bertentangan dengan perilaku default ResultSet, itu memberdayakan objek untuk memiliki fleksibilitas yang lebih besar. Fungsionalitas ini dapat dimanfaatkan oleh aplikasi untuk tidak hanya melintasi catatan tetapi juga membuatnya dapat diperbarui sehingga dapat memberikan layanan yang lebih baik. Meskipun perilaku standar dari kumpulan hasil tampaknya cukup tidak efisien dibandingkan dengan ResultSet . yang dapat digulir , ia memiliki kegunaannya sendiri dan oleh karena itu tidak tergantikan.