Easy-to-follow video tutorials help you learn software, creative, and business skills.Become a member
Once you have connected to a database, the next step is typically to send a request, and the most common sort of request is a simple SQL statement that retrieves data from the database. I'll show how to do this using the Statement interface and another interface named ResultSet, which encapsulates the data that's returned from the database. I'm working in a project called StaticSQL. This project's main class already has the code to connect to the database. It has the three strings, the User name, Password, and Connection string.
And I'm working with an HSQLDB database. In addition to the connection, I also need an instance of Statement and an instance of ResultSet. When you call methods of these interfaces, just as with the methods of the Connection class, they might throw an SQL exception. So typically, you'll declare the objects outside of the try block and then execute their methods within the try block, and that will make them have the lifetime invisibility that you need. I'll move my cursor after the Connection declaration, and I'll declare a Statement.
I'll type in the name of the interface and press Ctrl+Space, and I'll choose the version of statement from java.sql. Again, my goal is to make this code as portable between databases as possible. I'll name this object stmt and set it to null. Next, I'll declare my ResultSet, and again, this is the interface that will contain the data returned from the database. I'll name that RS, and again, I'll set it initially to null. Now I'm ready to create my statement. I will move the cursor after the code that's connecting to the database, and I will make a little bit of space.
I'll instantiate the statement using this code, stmt, the name of the object, equals conn.create statement. Notice that there are a few different versions of the create statement method. A default Statement object is returned when you don't pass in any arguments. There's also a version of the method where you can set the type of the ResultSet and its concurrency, and that's the version that I'm going to use. The default ResultSet type will differ from one database to another. With MySQL, the default ResultSet object is scrollable. That means that you can move the cursor up and down, going to the first row, the last row, and moving around as you like.
But with many databases, including HSQLDB, the default ResultSet type is forward only, meaning that the cursor will start before the data, and you'll be able to move forward to the end, but you won't be able to move back again. I'd like to set up my code to override that default and get a ResultSet that's scrollable. So I'm going to set the ResultSet type to a constant that looks like this. ResultSet, and I'll choose the constant TYPE_SCROLL_INSENSITIVE. That means that it's scrollable, but it won't be sensitive to any changes in the underlying data.
Essentially, it's a read-only ResultSet. Now I also need to set something called resultSetConcurrency, and this will indicate whether I'm working with a read-only ResultSet or an updatable ResultSet, a ResultSet that has a live connection to the underlying database. For the best performance, if I'm only going to be reading the data, I'll set the ResultSet to read-only, and I'll do that with another constant of ResultSet called CONCUR_READ_ONLY. So now I have created my statement object, and I'm ready to send the request to the database.
I'll instantiate my rs or ResultSet object, and I'll get data back by calling the Statement object, executeQuery method. When you call executeQuery, you can pass in any StaticSQL string. The nature of the SQL command is determined by the database you're working with. There's a common set of SQL commands that work across all databases, but there are many variations from one database to another. So again, for portability, I'm going to keep it simple. I'll call the executeQuery method, and I'll execute the SQL statement select asterisk from states.
States is the name of a database table that exists both in the MySQL database and the HyperSQL database that I'm working with. Now, to test the results, I'm going to find out how many rows are returned. In JDBC, there isn't a single property of the ResultSet object that you can look at. So instead, you move the cursor to the last row of the ResultSet and then find out what row number you're on. I'll use this code rs.last. The last method means move the cursor to the end of the ResultSet, and then I'll do a little bit of system output, and I'll output a string of number of rows, and I'll append to that the result of the method getRow, which looks like this, rs.getRow.
The getRow method returns an integer value, which represents the current row number. The JDBC ResultSet starts numbering its rows from one. So if I have a table of three rows, the getRow method would return one for the first row, two for the second, and three for the third. That's different than a Java array which starts counting at zero. And as long as you know the difference between the two, the numbering system for arrays versus the numbering system for databases, you'll be in good shape. I'll comment out the remaining System out Command, saying I'm connected, because now I'm interested in finding out how many rows of data I have.
So that's it. I'll save my changes, and I'll run the code. And I get back the message number of rows 50, and that's correct. There are 50 states and 50 rows in the states table in my database. I'll clean up my code, I'll delete unneeded comments and close up some extra white space, and then I'll test it one last time, and I'll see that I'm successfully connecting, that I'm getting back a scrollable ResultSet where I can move the cursor up down and back and forth as much as I need to, and I'm able to get the data back that I need.
Finally, I'll make sure that I have closed my resources. I'll return to my code, and I move down to my finally block where I am checking for the connection, making sure it's not null, and then closing it. Just like the Connection object, you need to explicitly close your Statement object and your ResultSet object. I'm going to copy this code and paste it in a couple of times. You should close objects in reverse order for how they were created. So the Connection was created first, then the Statement, and then the ResultSet, so I'm going to close them in reverse order.
I'll change my first if clause to rs, and if it's not null I'll close it, then I'll change the second block to the Statement, changing both the conditional logic and the call to the close method. All three of these interfaces have this close method, and again, it's up to you as the developer to make sure that you're closing these resources when you're done. If you forget to close a resource, with a file-based database you'll probably be fine, but with a network environment you might end up leaving a connection open to your database server, and that can cause problems at the server level later on.
Just make sure you have closed all of your resources when you're finished, and you'll be in great shape. Having made some more changes, I'll run the code one last time. I'm seeing I'm connecting and getting the data back, and so all this code is complete. And this can be used as a good model for how you execute any StaticSQL statement.
Get unlimited access to all courses for just $25/month.Become a member
61 Video lessons · 100226 Viewers
56 Video lessons · 113206 Viewers
71 Video lessons · 82090 Viewers
131 Video lessons · 39390 Viewers
Access exercise files from a button right under the course name.
Search within course videos and transcripts, and jump right to the results.
Remove icons showing you already watched videos if you want to start over.
Make the video wide, narrow, full-screen, or pop the player out of the page into its own window.
Click on text in the transcript to jump to that spot in the video. As the video plays, the relevant spot in the transcript will be highlighted.