The labs on this site need JavaScript to run. The same content is written out below.
Fundamentals › Spring
How does Java code send SQL to the database?
A database is a program that works separately from the Java program. (A database such as MySQL is a completely different program. H2, used in this lab, runs inside the Java program, but what the code does is the same.) For Java code to have the database do work, it does three things, following the convention called JDBC. First, it makes a connection (Connection) to the database. Second, it sends SQL as text over that connection. Third, it reads the returned result (ResultSet) one row at a time. Without a connection, SQL cannot be sent, and if the SQL text is wrong, the database answers with an error, which becomes a SQLException in Java (an exception, a signal that an error occurred). In this lab you add a conn.close() line to code that reads the name of the member whose id is 1 from the member table, or change the SQL text, and see the SQL the database received, the value Java printed, and the exception. (The code on the screen is treated as being inside the main method, so the import lines and the main declaration are left out. JdbcTemplate and JPA, which write this repeated code for you, are covered in the in-depth labs.)
Checked against real execution · Compiled and ran all six combinations in new Java processes on JDK 21 and H2 2.4.240, and checked the rules against the Java SE 21 API documentation
// The member table holds one row: (id 1, name kim)
// Connect: make a connection to the database that the URL points to
Connection conn = DriverManager.getConnection("jdbc:h2:mem:shop");
// Tool: the object that sends SQL over this connection
Statement st = conn.createStatement();
// Send: send the SQL text to the database and receive the result
ResultSet rs = st.executeQuery("SELECT name FROM member WHERE id = 1");
// Read: move to the next row. true if there is a row
boolean found = rs.next();
System.out.println(found);
System.out.println(rs.getString("name"));
Checked against real execution on JDK 21.0.12.1 and H2 2.4.240 (an in-memory database). It was not checked against execution on MySQL. All six combinations were checked by putting the code on the screen into a Main.java that has a main method (only import java.sql.* and the main declaration were added), compiling it with javax.tools, and running it in a new Java process for each combination. Before the run, the same process made the member table (id INT as the primary key, name VARCHAR(20)) and one row, (1, kim), and this preparation code is left out on the screen. The database is H2 running inside the Java process, so in reality it is in the same process, and it is not a separate program like MySQL. The order of connecting, sending SQL, and reading the result is the same, but that what travels between them is network communication was not checked in this lab. What was checked is the three items of the result table, that is, the SQL the database received, the value printed, and the exception. The SQL the database received was judged by whether that SELECT remained in INFORMATION_SCHEMA.QUERY_STATISTICS of H2 (the execution log), or the exception came from the parser of the database engine (org.h2.command.Parser) and the error message quoted that SQL. With the closed connection, neither was the case, and the exception came from JdbcConnection.checkClosed. The kind of exception is the SQLState and the error code of H2 (42102 table not found, 2000 no data to read, 90007 already closed object) put into the wording on the screen, and these codes are those of H2, so they may be different on MySQL. All three exceptions are subclasses of SQLException. The facts that the step sentences rely on were also checked by execution: that making a connection adds one session on the database side and closing it removes one, that createStatement alone leaves no SELECT in the execution log of the database and a SELECT is left after executeQuery, that calling getString before calling the next() method gives a SQLException, and that calling the next() method one more time gives false. The session count includes the one connection that the preparation code opened before the run. The execution log (QUERY_STATISTICS) did not show new records after it was read once (the cause was not checked), so a separate database was made for each point in time and read only once. To keep the code short, the code on the screen does not write the lines that close the connection and the ResultSet or the code that handles exceptions. Because the exception is not handled, the program stops at the line where the exception occurred and the lines below it do not run, and this was checked by the fact that the values of the later lines are not in the output. The Java SE 21 API documentation was opened and checked directly. The lab follows the java.sql package description (that DriverManager makes a connection, Statement sends SQL, and ResultSet receives the result), the description of Connection (that SQL is run inside a connection and the result comes back, and that createStatement throws a SQLException on a closed connection), Statement.executeQuery (that it returns a ResultSet and throws a SQLException on a closed Statement), the description of ResultSet (that the cursor is at first in front of the first row, that next moves one step and returns false if there is no row, and that a method that needs a current row throws a SQLException then), the description of SQLException (that it is an exception that carries the SQLState and an error code), and DriverManager.getConnection (that the URL has the form jdbc:subprotocol:name). From the H2 documentation (the features page), it was checked that jdbc:h2:mem:name points to one in-memory database with that name inside the same JVM, and that the in-memory database disappears when the last connection is closed. That H2 gives an error when a Statement made from a closed connection is used is not defined by the documentation but is a behavior observed on this H2 (the Statement documentation says only that it throws an exception on a closed Statement). This lab does not cover PreparedStatement and how to put values into SQL, SQL that changes data (executeUpdate), transactions, or the right way to close a connection (try-with-resources). JdbcTemplate, which reduces the repeated code, is covered in the in-depth lab "JdbcTemplate and exception translation", borrowing a connection instead of making a new one every time is covered in "Connection pool and OSIV", and JPA, which connects objects and tables, is covered in "What JPA solves".
Previous lab: Configuration files · Next lab: @Transactional
Struck-through text was removed from the first version of the code; highlighted text was added.