Java Database Connectivity

"Database connectivity lets your Java programs store, retrieve, and manipulate persistent data managed by a relational database — far more powerful and scalable than flat file storage."- Claude 2026

Database Connectivity

In another page we used file I/O to persist data. Files work for small, simple datasets, but as data grows — multiple tables, relationships between records, concurrent users — a relational database management system (RDBMS) becomes essential.

File I/O

Data stored in flat text files. Simple to set up, but no structure enforcement, no querying power, and no support for multiple users accessing data at the same time.

Database

Data stored in structured tables with defined columns and types. Supports complex queries, relationships between tables, data validation, and concurrent access by many users.

Java connects to databases through JDBC (Java Database Connectivity), an API included in the standard library. JDBC provides a uniform interface — the same Java code structure works whether you're talking to MySQL, PostgreSQL, SQLite, or any other RDBMS. The only things that change are the driver (a JAR file specific to your database) and the connection URL.

Learn More About JDBC
Structured Query Language (SQL)

Before writing Java code, you need to understand the SQL statements your program will send to the database. SQL breaks down into two main categories:

DDL — Data Definition Language

Creates and modifies the structure of your database.

CREATE TABLE characters (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(50) NOT NULL,
    char_class VARCHAR(50) NOT NULL
);

ALTER TABLE characters ADD level INT;

DROP TABLE characters;
DML — Data Manipulation Language

Works with the data inside your tables.

INSERT INTO characters (name, char_class)
    VALUES ('Hero', 'Warrior');

SELECT * FROM characters;

UPDATE characters
    SET char_class = 'Paladin'
    WHERE name = 'Hero';

DELETE FROM characters
    WHERE name = 'Hero';

Each of these statements will be sent from your Java program to the database through a JDBC connection. The database executes the SQL and returns results (or a confirmation) back to your program.

Practice SQL in Your Browser

You can try out SQL statements right now without installing anything. SQLize.online gives you a live MySQL database in the browser — no login required. Paste any of the SQL examples from this page, click Run, and see the results.

SQL References
Processing SQL Statements

JDBC uses three key interfaces to send SQL to the database and handle what comes back. Think of them as a pipeline:

1. Connection

Your active session with the database. You obtain one by calling DriverManager.getConnection() with a connection URL (and for MySQL, a username and password). Every database operation flows through this connection.

2. PreparedStatement

A precompiled SQL statement created from your Connection using connection.prepareStatement(sql). Placeholders written as ? in the SQL are filled in with setter methods like setString(1, value) before execution.

Always use PreparedStatement instead of building SQL strings with concatenation. Concatenating user input into SQL opens the door to SQL injection — a serious security vulnerability where malicious input gets executed as SQL code.

3. ResultSet

Holds the rows returned by a SELECT query. You iterate through it with resultSet.next(), which advances to the next row and returns false when there are no more rows. Column values are retrieved with typed getters like getString("name") or getInt("id").

The execution method you call depends on the type of SQL:

executeQuery()

For SELECT statements.
Returns a ResultSet.

executeUpdate()

For INSERT, UPDATE, DELETE, and DDL.
Returns an int (rows affected).

Working with Data

A typical JDBC workflow follows a predictable pattern:

Step What Happens Key Method
Connect Establish a session with the database DriverManager.getConnection(url)
Prepare Create a statement with your SQL connection.prepareStatement(sql)
Set Parameters Fill in ? placeholders (1-indexed) pstmt.setString(1, "Hero")
Execute Send the SQL to the database executeQuery() or executeUpdate()
Process Loop through returned rows (SELECT only) while (rs.next()) { ... }
Close Release resources Automatic with try (...) { }

Inserting data uses executeUpdate() with an INSERT statement. Each ? placeholder is filled using the appropriate setter. Positions are 1-indexed — the first ? is position 1, the second is position 2.

Querying data uses executeQuery() with a SELECT statement. The returned ResultSet is processed row by row inside a while loop.

Updating and deleting also use executeUpdate(). The return value tells you how many rows were affected, which is useful for confirming the operation worked.

File operations in Java use try-with-resources to automatically close readers and writers. JDBC works the same way — wrap your Connection, PreparedStatement, and ResultSet in a try (...) { } block, and Java closes them automatically when the block exits, even if an exception occurs.

Additional Database Connectivity Information
Connection URL

The JDBC URL tells Java where your database lives. The format varies by database:

SQLite:
jdbc:sqlite:game.db

MySQL:
jdbc:mysql://localhost:3306/game

SQLite creates a file (game.db) in the same folder as your program. MySQL connects to a running server on port 3306.

The JDBC Driver

Each database needs its own driver — a JAR file you add to your project's classpath when you run the program.

For SQLite, the driver is sqlite-jdbc. For MySQL, it's MySQL Connector/J. In modern Java (6+), the driver registers itself automatically — no Class.forName() call is needed.

Exception Handling

The primary exception is SQLException, which covers connection failures, SQL syntax errors, and constraint violations. Always wrap JDBC operations in try-catch blocks.

The try-with-resources syntax handles closing automatically — exactly like file I/O.

Security

Never concatenate user input directly into SQL strings — always use PreparedStatement with ? placeholders.

Never hard-code database credentials in source code for production applications. Use environment variables or configuration files instead.

Complete Database Application

This complete example demonstrates every core JDBC operation: creating a table, inserting rows, querying, updating, and deleting. It uses SQLite, which stores the entire database in a single file — no server installation, no username/password, no background services to manage.

import java.sql.*;

public class PartyDatabase {

    public static void main(String[] args) {

        String url = "jdbc:sqlite:game.db";

        try (Connection conn = DriverManager.getConnection(url)) {

            Statement stmt = conn.createStatement();
            stmt.executeUpdate(
                "CREATE TABLE IF NOT EXISTS characters (" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
                "name VARCHAR(50) NOT NULL, " +
                "char_class VARCHAR(50) NOT NULL)"
            );
            System.out.println("Table ready.");

            String insertSQL = "INSERT INTO characters (name, char_class) VALUES (?, ?)";
            try (PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {
                String[][] party = {{"Hero", "Warrior"}, {"Zara", "Mage"}, {"Fletch", "Archer"}};
                for (String[] c : party) {
                    pstmt.setString(1, c[0]);
                    pstmt.setString(2, c[1]);
                    pstmt.executeUpdate();
                }
            }
            System.out.println("Characters inserted.\n");

            String selectSQL = "SELECT id, name, char_class FROM characters";
            try (PreparedStatement pstmt = conn.prepareStatement(selectSQL);
                 ResultSet rs = pstmt.executeQuery()) {
                System.out.println("Current party:");
                while (rs.next()) {
                    System.out.printf("  [%d] %s (%s)%n",
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getString("char_class"));
                }
            }

            String updateSQL = "UPDATE characters SET char_class = ? WHERE name = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(updateSQL)) {
                pstmt.setString(1, "Paladin");
                pstmt.setString(2, "Hero");
                int rows = pstmt.executeUpdate();
                System.out.println("\nUpdated " + rows + " row(s): Hero is now a Paladin.");
            }

            String deleteSQL = "DELETE FROM characters WHERE name = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(deleteSQL)) {
                pstmt.setString(1, "Fletch");
                int rows = pstmt.executeUpdate();
                System.out.println("Deleted " + rows + " row(s): Fletch removed.\n");
            }

            try (PreparedStatement pstmt = conn.prepareStatement(selectSQL);
                 ResultSet rs = pstmt.executeQuery()) {
                System.out.println("Updated party:");
                while (rs.next()) {
                    System.out.printf("  [%d] %s (%s)%n",
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getString("char_class"));
                }
            }

        } catch (SQLException e) {
            System.out.println("Database error: " + e.getMessage());
        }
    }

}
Table ready.
Characters inserted.

Current party:
  [1] Hero (Warrior)
  [2] Zara (Mage)
  [3] Fletch (Archer)

Updated 1 row(s): Hero is now a Paladin.
Deleted 1 row(s): Fletch removed.

Updated party:
  [1] Hero (Paladin)
  [2] Zara (Mage)
Running the Application

This example uses SQLite, which requires no database server — just a single JAR file. You need two things: the JDK and the SQLite JDBC driver.

1. Download the SQLite JDBC Driver

Go to sqlite-jdbc on GitHub. Under the latest release, expand the Assets section and download the file named sqlite-jdbc-<version>.jar (for example, sqlite-jdbc-3.51.3.0.jar). Save this JAR file in the same folder where you will save your .java file.

2. Save, Compile, and Run

Save the code above as PartyDatabase.java in the same folder as the JAR. Open a terminal in that folder and run:

javac PartyDatabase.java
java -cp .:sqlite-jdbc-3.51.3.0.jar PartyDatabase

On Windows, replace the : with a ; in the classpath:

java -cp .;sqlite-jdbc-3.51.3.0.jar PartyDatabase

Adjust the JAR filename to match the version you downloaded. The -cp flag tells Java where to find both your compiled class (. means the current folder) and the SQLite driver.

What Happens When You Run It

The first time you run the program, SQLite creates a file called game.db in the same folder. This file is the database. You can delete it and run the program again to start fresh. If you run the program a second time without deleting game.db, the characters from the first run are still in the table — that's persistence at work.

Troubleshooting

ClassNotFoundException: the JAR file is not on your classpath. Make sure the -cp path includes the exact JAR filename and that the JAR is in the same directory as your compiled .class file.

"No suitable driver found": same cause — the JAR isn't being found. Double-check the filename and path separator (: on Mac/Linux, ; on Windows).

Duplicate entries on re-run: the database file persists between runs. Delete game.db before running again, or change CREATE TABLE to CREATE TABLE IF NOT EXISTS and add logic to clear old data.

Switching to MySQL

The example above uses SQLite to keep setup simple. When you're ready to work with MySQL — a full client-server database used in production applications — the JDBC code stays almost entirely the same. Only three things change:

SQLite MySQL
Connection URL jdbc:sqlite:game.db jdbc:mysql://localhost:3306/game
Connection call getConnection(url) getConnection(url, "root", "password")
Auto-increment AUTOINCREMENT AUTO_INCREMENT

Everything else — the PreparedStatements, the ResultSet processing, the try-with-resources pattern, the parameterized queries — is identical. That's the power of JDBC's database-independent design: learn it once and it works with any database.

What You Need to Install for MySQL

MySQL is a client-server database, which means you need to install and run a database server on your machine before your Java program can connect to it. This involves installing MySQL, setting a root password, creating a database, and downloading the MySQL JDBC driver (Connector/J). The following tutorials walk through every step with screenshots:

Mac

Install MySQL on Mac (CodeStudy)

Covers both Homebrew and the DMG installer, verifying installation, and logging in for the first time.

Windows

Install MySQL on Windows (Dataquest)

Step-by-step using the MySQL Installer with screenshots for every screen in the wizard.

After Installing MySQL

Once MySQL is running, open a terminal (Mac) or the MySQL Command Line Client (Windows), log in, and create the database:

mysql -u root -p
CREATE DATABASE game;
exit;

Then download MySQL Connector/J (choose "Platform Independent", download the ZIP, and grab the .jar file inside). Place it in the same folder as your .java file and compile/run the same way:

javac PartyDatabase.java
java -cp .:mysql-connector-j-9.2.0.jar PartyDatabase
Additional Learning Resources
→ This page was created with help from Claude AI.