Bij het ophalen van een lijst met records via query's, moeten we ze vaak opslaan in een object dat heen en weer kan bewegen, en indien nodig wordt bijgewerkt. Dit artikel illustreert deze veelgebruikte techniek bij het programmeren van databases met expliciete codes en voorbeeldscenario's.
Over ResultSet
De ResultSet is een interface gedefinieerd in de java.sql pakket. Het vertegenwoordigt een tabel met gegevens die worden geretourneerd door een Statement voorwerp. Een Verklaring object wordt gebruikt om SQL-query's naar de database uit te voeren. Het ResultSet-object handhaaft een cursor die naar het huidige record in de databasetabel wijst. Als gevolg hiervan kan het effectief worden gebruikt om op verschillende rijen heen en weer te positioneren met behulp van first() , vorige() , volgende() , en laatste() methoden volgens de vereisten. Aanvankelijk was de ResultSet object is gepositioneerd op een locatie vóór de eerste rij. Dit is de reden waarom een ResultSet traversal begint altijd als volgt:
while(resultSet.next()) { // ... }
Merk op dat de ResultSet object wordt op de eerste rij geplaatst door next() . uit te voeren methode bij het betreden van de lus, omdat, zoals reeds vermeld, de ResultSet object bevindt zich aanvankelijk op een positie net voor de eerste rij. Het moet dus op zijn minst op de eerste rij worden gezet, bijvoorbeeld om een geldig record te krijgen. Het kan worden beschouwd als een waarde -1 in een matrixpositie waar een aanwijzer/index naar verwijst. Het moet eerst worden verplaatst naar ten minste de 0-locatie om een geldige waarde uit de array te krijgen.
Nu, zoals we hebben vermeld, kunnen we door records scrollen met behulp van de ResultSet voorwerp. Maar deze mogelijkheid is niet standaard. Het standaardgedrag van de ResultSet object is dat het niet kan worden bijgewerkt en dat de cursor die het bezit feitelijk in één richting beweegt, alleen vooruit. Dit betekent dat we de records slechts één keer en alleen in voorwaartse richting kunnen doorlopen. Er zijn echter manieren om het flexibel te maken, zodat de ResultSet is niet alleen updatebaar maar ook scrollbaar.
We zullen ze zo zien in twee afzonderlijke programma's.
Scrollbare ResultSet
Laten we eerst de ResultSet . maken object scrollbaar. Scrolbaar betekent dat zodra de ResultSet object is gemaakt, kunnen we de opgehaalde records in elke richting doorlopen, vooruit en achteruit, zoals we willen. Dit biedt de mogelijkheid om het laatste record, het eerste record, het volgende record en het vorige record te lezen.
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---------------------------------"+ "------------------------------------"); } }
Uitvoer
- Verbinding tot stand gebracht.
- SQL-query uitvoeren...
- ResultSet-object succesvol gemaakt.
- Nu begint wat RecordSet-scrolling...
------------------------------------------------------------- 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 -------------------------------------------------------------
- Dat is alles. RecordSet scrollen stopt.
Merk op dat de schuifbare ResultSet object is het resultaat van de uitvoering van de executeQuery() methode verkregen via de instantie van Statement of PreparedStatement . Het type ResultSet object dat we willen maken, moet expliciet worden gedeclareerd in de Statement object door gedefinieerde scroll-type constanten.
- ResultSet.TYPE_FORWARD_ONLY: Dit is het standaardtype.
- ResultSet.TYPE_SCROLL_INSENSITIVE: Maakt heen en weer bewegen mogelijk, maar is ongevoelig voor ResultSet updates.
- ResultSet.TYPE_SCROLL_SENSITIVE: Maakt heen en weer bewegen mogelijk, maar is gevoelig voor ResultSet updates.
Er worden andere constanten gebruikt, zoals CONCUR_READ_ONLY , wat betekent dat de ResultSet kan niet worden bijgewerkt. Er is nog een constante, CONCUR_UPDATABLE , wat het tegenovergestelde betekent, wat de ResultSet . betekent kan worden bijgewerkt.
Bij te werken ResultSet
Een bijwerkbare ResultSet maken betekent dat het record waarnaar het verwijst niet alleen kan worden doorkruist, maar ook kan worden bijgewerkt. De wijzigingen worden onmiddellijk in de database bewaard en weergegeven door de ResultSet object in realtime.
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---------------------------------"+ "------------------------------------"); } }
De bijwerkbare ResultSet is met name handig wanneer we bepaalde waarden willen bijwerken nadat we een vergelijking hebben gemaakt door heen en weer te gaan door de opgehaalde records. Het aanmaakproces is vergelijkbaar met het voorgaande programma, maar de ResultSet constanten die hier worden gebruikt zijn TYPE_SCROLL_SENSITIVE en CONCUR_UPDATABLE .
Conclusie
In tegenstelling tot het standaardgedrag van de ResultSet, het stelt het object in staat om meer flexibiliteit te hebben. Deze functionaliteit kan door de toepassing worden gebruikt om niet alleen door records te bladeren, maar ze ook te updaten, zodat ze een betere service kunnen bieden. Hoewel het standaardgedrag van een resultatenset nogal inefficiënt lijkt in vergelijking met de schuifbare ResultSet , het heeft zijn eigen gebruik en is daarom onvervangbaar.