Search

Database Programming With Java + JDBC: Part 3/4

0 views

Setting Up the Environment and Establishing a Database Connection

To start building a Java application that talks to a relational database, you first need to bring the JDBC API into your project and point it at the database you plan to use. In this example, the target database is MySQL, so the JDBC driver for MySQL is required. The driver is simply a library that implements the JDBC interfaces so that Java can send SQL statements to MySQL and interpret the responses.

Once the driver library is on the classpath, the next step is to write a small helper that loads the driver class and opens a Connection. The driver class name for the current MySQL Connector/J library is com.mysql.cj.jdbc.Driver, but the older org.gjt.mm.mysql.Driver still works for legacy code. Loading the driver class registers it with the DriverManager, which is responsible for locating a suitable driver when you ask for a connection.

In the code below, the getConnection method does precisely that. It declares the driver class name and the database URL, then attempts to open a connection using DriverManager.getConnection. The URL follows the pattern jdbc:mysql:///; if the host is omitted, it defaults to localhost, and if a database name is omitted, the connection points to the server root. Credentials are passed as separate arguments; in this simplified example the user and password strings are empty because the local MySQL instance allows anonymous login.

Prompt
public class JDBCDemo1 {</p> <p> private static final String DB_DRIVER = "org.gjt.mm.mysql.Driver";</p> <p> private static final String DB_URL = "jdbc:mysql:///test_db";</p> <p> public Connection getConnection() throws ClassNotFoundException, SQLException {</p> <p> Class.forName(DB_DRIVER);</p> <p> return DriverManager.getConnection(DB_URL, "", "");</p> <p> }</p> <p>}</p>

Both ClassNotFoundException and SQLException are declared on the method signature so that callers can decide how to handle missing drivers or connection failures. In a production application, you would likely log the error and either retry or abort the startup process. For educational purposes, throwing the exception lets the caller decide the next step.

Before any SQL statements can run, you need to verify that the database exists and that the connection can reach it. Running getConnection at the beginning of the main method, and catching any exceptions that surface, gives a quick sanity check that the environment is set up correctly. If the connection fails, the program will terminate early, saving time and preventing later crashes caused by a null Connection reference.

Building the Address Book Table with SQL DDL

With a working Connection in hand, the next logical step is to create the database schema that will hold the address book entries. In this example, a single table named address_book is created. The table contains three columns: nickname (the primary key), name, and email. The nickname field is declared as VARCHAR(20) and marked NOT NULL to enforce uniqueness, while the name and email columns are optional.

DDL statements are executed through a Statement object. The createTable method builds a string that contains the SQL command and then passes it to executeUpdate. If the table already exists, MySQL will throw an exception; in a real application you might catch that specific error and ignore it, but for demonstration purposes the exception is allowed to propagate.

Prompt
public void createTable(Connection con) throws SQLException {</p> <p> Statement stmt = null;</p> <p> String query;</p> <p> try {</p> <p> query = "CREATE TABLE address_book (" +</p> <p> "nickname VARCHAR(20) NOT NULL," +</p> <p> "name VARCHAR(30)," +</p> <p> "email VARCHAR(50)," +</p> <p> "PRIMARY KEY (nickname))";</p> <p> stmt = con.createStatement();</p> <p> stmt.executeUpdate(query);</p> <p> } finally {</p> <p> if (stmt != null) {</p> <p> stmt.close();</p> <p> }</p> <p> }</p> <p>}</p>

Notice the clean separation between the SQL string and the Java code that executes it. The try/finally pattern guarantees that the Statement resource is closed regardless of whether the query succeeds. Closing resources is essential; failing to do so can leave database connections open, eventually exhausting the pool and causing subsequent queries to fail.

When writing DDL for MySQL, it is helpful to remember that MySQL is forgiving about column order but strict about data types. The chosen lengths for VARCHAR columns are large enough to store typical names and email addresses without wasting space. The PRIMARY KEY constraint ensures that every entry has a unique nickname, which simplifies lookups and updates later on.

Once the createTable method is verified, the next phase is to enable users to add data and search for existing entries. These operations illustrate the use of DML (Data Manipulation Language) statements like INSERT and SELECT, as well as the importance of properly handling user input to avoid SQL injection vulnerabilities.

Managing Records: Inserting and Querying Address Book Entries

The add method demonstrates how to persist a new address book record. It builds an INSERT statement by concatenating the nickname, name, and email parameters into the SQL string. While concatenation is easy, it opens the door to SQL injection if the inputs are not sanitized. In a real application you would use a PreparedStatement to bind parameters safely. For the sake of brevity, this example uses direct string concatenation but keeps the parameters in separate variables so that the developer can see where each value ends up.

Prompt
public int add(Connection con, String nickName, String name, String email)</p> <p> throws SQLException {</p> <p> int n = 0;</p> <p> String query;</p> <p> try {</p> <p> query = "INSERT INTO address_book(nickname, name, email) " +</p> <p> "VALUES('" + nickName + "', '" + name + "', '" + email + "')";</p> <p> n = stmt.executeUpdate(query);</p> <p> } finally {</p> <p> }</p> <p> }</p> <p> return n;</p> <p>}</p>

The method returns the number of rows affected. For a successful insert, that number is 1. The caller can use this return value to confirm that the operation succeeded or to trigger error handling if zero rows were updated.

Retrieving an entry is handled by the lookup method. It constructs a SELECT statement that filters by nickname, executes it, and then processes the ResultSet. The code pulls each column value in the order it appears in the SELECT list. If a row is found, a new AddressBookEntry object is instantiated and returned; otherwise, the method returns null. Proper cleanup of both the ResultSet and the Statement is again guaranteed by a finally block.

Prompt
public AddressBookEntry lookup(Connection con, String nickName)</p> <p> AddressBookEntry entry = null;</p> <p> ResultSet rs = null;</p> <p> String query;</p> <p> try {</p> <p> query = "SELECT nickname, name, email FROM address_book " +</p> <p> "WHERE nickname = '" + nickName + "'";</p> <p> rs = stmt.executeQuery(query);</p> <p> if (rs.next()) {</p> <p> String name = rs.getString(2);</p> <p> String email = rs.getString(3);</p> <p> entry = new AddressBookEntry(nickName, name, email);</p> <p> }</p> <p> } finally {</p> <p> try {</p> <p> if (rs != null) rs.close();</p> <p> } catch (Exception ignore) {}</p> <p> try {</p> <p> if (stmt != null) stmt.close();</p> <p> }</p> <p> return entry;</p> <p>}</p>

Because the method uses SELECT nickname, name, email, the column indices start at 1 for nickname, 2 for name, and 3 for email. The first column is already known from the method argument, so only the remaining two are fetched from the result set. If the nickname does not exist in the table, the method will skip the if (rs.next()) block and return null, which callers interpret as “no such entry.”

Both add and lookup illustrate a common pattern in JDBC: build a query string, create a statement, execute the query, process the result, and finally close the statement (and result set, if applicable). This pattern keeps the code simple while ensuring that resources are not leaked.

Running the Demo: Console Interaction and Control Flow

The main method ties everything together. It first creates an instance of the demo class and obtains a database connection. A BufferedReader wrapped around System.in reads user input from the console. A loop presents a menu of options - create table, add entry, lookup entry, or quit - until the user chooses to exit.

Input parsing is performed with Integer.parseInt, wrapped in a try/catch to handle non-numeric entries. The switch statement routes each choice to the corresponding method. After each operation, a helper method called printResult displays a friendly message so the user knows the outcome.

Prompt
public static void main(String[] args) {</p> <p> JDBCDemo1 jdbcDemo = new JDBCDemo1();</p> <p> Connection con = null;</p> <p> BufferedReader in = new BufferedReader(new InputStreamReader(System.in));</p> <p> boolean continueFlag = true;</p> <p> String choiceStr;</p> <p> int choice;</p> <p> String nickName, name, email;</p> <p> AddressBookEntry entry;</p> <p> try {</p> <p> con = jdbcDemo.getConnection();</p> <p> while (continueFlag) {</p> <p> System.out.println();</p> <p> System.out.println(" <strong><em> Address Book Menu </strong></em>");</p> <p> System.out.println("Choose your option from 1-4 below");</p> <p> System.out.println("1. Create the addressbook table");</p> <p> System.out.println("2. Add an entry to the addressbook");</p> <p> System.out.println("3. Search an entry in the addressbook");</p> <p> System.out.println("4. Quit");</p> <p> System.out.print("Enter your choice [1-4]: ");</p> <p> choiceStr = in.readLine();</p> <p> try {</p> <p> choice = Integer.parseInt(choiceStr);</p> <p> } catch (NumberFormatException nfe) {</p> <p> System.out.println();</p> <p> System.out.println("Invalid choice.");</p> <p> continue;</p> <p> }</p> <p> switch (choice) {</p> <p> case 1:</p> <p> jdbcDemo.createTable(con);</p> <p> printResult("Table created successfully.");</p> <p> break;</p> <p> case 2:</p> <p> System.out.println("Enter the following information.");</p> <p> System.out.print("Nickname: ");</p> <p> nickName = in.readLine();</p> <p> System.out.print("Name: ");</p> <p> name = in.readLine();</p> <p> System.out.print("Email: ");</p> <p> email = in.readLine();</p> <p> jdbcDemo.add(con, nickName, name, email);</p> <p> printResult("Entry added successfully.");</p> <p> case 3:</p> <p> System.out.print("Enter the nickname to search: ");</p> <p> entry = jdbcDemo.lookup(con, nickName);</p> <p> if (entry != null) {</p> <p> printResult(entry.toString());</p> <p> } else {</p> <p> printResult("No such nickname in the addressbook.");</p> <p> }</p> <p> case 4:</p> <p> continueFlag = false;</p> <p> default:</p> <p> System.out.println();</p> <p> System.out.println("Invalid choice.");</p> <p> }</p> <p> }</p> <p> } catch (Exception ex) {</p> <p> ex.printStackTrace();</p> <p> } finally {</p> <p> try {</p> <p> if (con != null) con.close();</p> <p> } catch (SQLException ignored) {}</p> <p> if (!continueFlag) {</p> <p> System.out.println("Thank you for using the addressbook.");</p> <p> }</p> <p> }</p> <p>}</p>

The printResult helper simply prefixes the message with “RESULT: ” so that success messages stand out in the console. The final finally block closes the database connection and displays a polite goodbye message when the loop terminates. If an exception escapes the try block, the stack trace is printed to help diagnose issues during development.

Running this application from the command line, you will see a menu that guides you through creating the table, adding a couple of records, and then searching for them. The entire flow demonstrates how Java interacts with a database through JDBC, while keeping the code readable and maintainable.

This hands‑on example forms a foundation for more complex applications. Once you grasp how to load drivers, establish connections, create tables, and perform CRUD operations, you can extend the design to use prepared statements, connection pools, and ORM frameworks. The basic patterns illustrated here remain the same, so the knowledge stays useful even as you adopt newer libraries or migrate to other relational databases.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles