How do I connect to a MySQL database using JDBC?

Connecting to a MySQL database using JDBC involves a few straightforward steps: adding the driver, defining your connection credentials, and using the DriverManager to open a session.

1. Add the MySQL Connector Dependency

First, ensure you have the MySQL JDBC driver in your project. If you are using Maven, add this to your pom.xml:

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>9.1.0</version> <!-- Use the latest version -->
</dependency>

2. Basic Connection Code

Here is a clean example of how to establish a connection and execute a simple query:

package org.kodejava.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class MySqlConnection {
    // JDBC URL: jdbc:mysql://[host]:[port]/[database_name]
    private static final String URL = "jdbc:mysql://localhost:3306/your_database";
    private static final String USER = "root";
    private static final String PASSWORD = "your_password";

    public static void main(String[] args) {
        // Try-with-resources automatically closes Connection, Statement, and ResultSet
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {

            if (conn != null) {
                System.out.println("Connected to the database!");

                // Example: Execute a simple query
                String sql = "SELECT * FROM users";
                try (Statement stmt = conn.createStatement();
                     ResultSet rs = stmt.executeQuery(sql)) {

                    while (rs.next()) {
                        System.out.println("User: " + rs.getString("username"));
                    }
                }
            }

        } catch (SQLException e) {
            System.err.println("SQL State: " + e.getSQLState());
            System.err.println("Error Code: " + e.getErrorCode());
            System.err.println("Message: " + e.getMessage());
        }
    }
}

Key Components:

  • JDBC URL: For MySQL, it always starts with jdbc:mysql://. You can also append parameters like ?useSSL=false&serverTimezone=UTC to handle specific environment requirements.
  • DriverManager: The factory class that manages JDBC drivers and creates connections.
  • SQLException: Always wrap your JDBC code in a try-catch block, as database operations are prone to external failures (network issues, incorrect credentials, etc.).
  • Try-with-resources: In modern Java, you don’t need to manually call .close() in a finally block if you declare the resources inside the try (...) parentheses.

How do I set up JDBC in a Java project?

Setting up JDBC (Java Database Connectivity) involves a few key steps: adding the database driver to your project, establishing a connection, and executing your SQL statements.

1. Add the JDBC Driver Dependency

First, you need the driver for your specific database (e.g., MySQL, PostgreSQL, H2) in your pom.xml.

For MySQL, you would add:

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>9.1.0</version>
</dependency>

2. Establish a Connection

You use the DriverManager.getConnection() method. It requires a Connection URL, username, and password.

  • URL Format: jdbc:mysql://[host]:[port]/[database_name]
  • Modern Java Tip: You no longer need to call Class.forName("com.mysql.cj.jdbc.Driver") in modern JDBC (4.0+).

3. Use Try-With-Resources

Always use try-with-resources to ensure that the Connection, Statement, and ResultSet are closed automatically, preventing memory leaks.

Basic Example

Here is a concise template to get you started:

package org.kodejava.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcSetup {
    private static final String URL = "jdbc:mysql://localhost:3306/your_database";
    private static final String USER = "root";
    private static final String PASSWORD = "your_password";

    public static void main(String[] args) {
        String query = "SELECT id, name FROM users";

        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name"));
            }
        } catch (SQLException e) {
            System.err.println("Connection failed!");
            e.printStackTrace();
        }
    }
}

How do I use JSON libraries like Jackson or Gson in modern Java?

In modern Java, using JSON libraries like Jackson or Gson is the standard way to handle data exchange, as the Java Standard Library does not include a built-in JSON parser.

With Java 25, you can take advantage of Records for clean data models and Text Blocks for readable JSON strings in your code.

1. Using Jackson (Industry Standard)

Jackson is highly recommended for modern applications, especially within the Spring and Jakarta EE ecosystems.

Maven Dependency:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.18.2</version>
</dependency>

Code Example:

import com.fasterxml.jackson.databind.ObjectMapper;

// 1. Define a Record (Modern Java way)
public record User(Long id, String name) {}

public class JacksonDemo {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        // Serialization (Object to JSON)
        User user = new User(1L, "Duke");
        String json = mapper.writeValueAsString(user);
        System.out.println("JSON: " + json);

        // Deserialization (JSON to Object)
        String inputJson = """
                {
                    "id": 2,
                    "name": "Java"
                }
                """;
        User decodedUser = mapper.readValue(inputJson, User.class);
        System.out.println("User Name: " + decodedUser.name());
    }
}

2. Using Gson (Google’s Library)

Gson is known for its simplicity and ease of use for smaller projects or quick utilities.

Maven Dependency:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.11.0</version>
</dependency>

Code Example:

import com.google.code.gson.Gson;
import com.google.code.gson.GsonBuilder;

public class GsonDemo {
    public static void main(String[] args) {
        // Use GsonBuilder for custom configurations like Pretty Printing
        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        // Serialization
        User user = new User(10L, "Modern Java");
        String json = gson.toJson(user);
        System.out.println(json);

        // Deserialization
        User fromJson = gson.fromJson(json, User.class);
        System.out.println("ID from JSON: " + fromJson.id());
    }
}

Key Comparisons & Tips

  • Records Support: Both Jackson (2.12+) and Gson (2.10+) support Java Records natively. This is the preferred way to create POJOs for data mapping.
  • Immutability: Since Records are immutable, these libraries use reflection or canonical constructors to populate the data, which is much safer than traditional setter-based beans.
  • Performance: Jackson is generally faster and offers more features for complex mapping (like @JsonProperty for renaming fields).
  • Integration: If you are using Spring Boot, Jackson is already included and configured for you.

Integrating with HttpClient

When fetching data from an API using the java.net.http.HttpClient, you typically receive a String which you then pass to these libraries:

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
User user = mapper.readValue(response.body(), User.class);

For more advanced use cases, you can even write a custom BodyHandler that uses Jackson to parse the stream directly, saving memory on large JSON payloads.

How do I use InetAddress to resolve hostnames?

To resolve a hostname to an IP address (or vice versa) in Java, you use the java.net.InetAddress class. This class provides static factory methods to perform DNS lookups.

Here are the most common ways to use it:

1. Resolve a Hostname to an IP Address

Use InetAddress.getByName(String host) to get the primary IP address associated with a domain.

package org.kodejava.net;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class ResolveHost {
    public static void main(String[] args) {
        try {
            // Resolve a domain name to its IP address
            InetAddress address = InetAddress.getByName("www.google.com");

            System.out.println("Host Name: " + address.getHostName());
            System.out.println("IP Address: " + address.getHostAddress());
        } catch (UnknownHostException e) {
            System.err.println("Could not resolve host: " + e.getMessage());
        }
    }
}

2. Resolve All IP Addresses for a Host

Large websites often have multiple IP addresses for load balancing. You can retrieve all of them using getAllByName(String host).

try {
    InetAddress[] addresses = InetAddress.getAllByName("www.google.com");
    for (InetAddress addr : addresses) {
        System.out.println(addr.getHostAddress());
    }
} catch (UnknownHostException e) {
    e.printStackTrace();
}

3. Reverse DNS Lookup (IP to Hostname)

If you have an IP address and want to find the hostname, use getByName() with the IP string and then call getHostName().

try {
    InetAddress address = InetAddress.getByName("8.8.8.8");
    // This triggers a reverse DNS lookup
    System.out.println("The hostname for 8.8.8.8 is: " + address.getHostName());
} catch (UnknownHostException e) {
    e.printStackTrace();
}

Key Methods Summary:

  • getHostAddress(): Returns the IP address string in textual presentation (e.g., “142.250.190.36”).
  • getHostName(): Returns the hostname for this IP address. If the operation is successful, it will perform a reverse lookup.
  • getCanonicalHostName(): Returns the fully qualified domain name (FQDN).

Important Note on Exceptions

Always wrap these calls in a try-catch block for UnknownHostException. This exception is thrown if the DNS server cannot find the host or if the network is unreachable.

How do I implement a simple TCP client and server?

To implement a simple TCP client and server in Java, you use the ServerSocket class for the server and the Socket class for the client.

Here is a straightforward example of both, where they exchange simple text messages.

1. The TCP Server

The server listens on a specific port and waits for a client to connect. Once connected, it opens input and output streams to communicate.

package org.kodejava.net;

import java.io.*;
import java.net.*;

public class SimpleTCPServer {
    public static void main(String[] args) {
        int port = 8080;

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);

            // Wait for a client connection
            try (Socket socket = serverSocket.accept()) {
                System.out.println("Client connected!");

                // Setup streams for communication
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);

                // Read message from a client
                String clientMessage = reader.readLine();
                System.out.println("Received from client: " + clientMessage);

                // Send a response back
                writer.println("Hello from Server!");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. The TCP Client

The client connects to the server’s IP address (or localhost) and the same port number.

package org.kodejava.net;

import java.io.*;
import java.net.*;

public class SimpleTCPClient {
    public static void main(String[] args) {
        String hostname = "localhost";
        int port = 8080;

        try (Socket socket = new Socket(hostname, port)) {
            // Setup streams for communication
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            // Send a message to the server
            writer.println("Hello from Client!");

            // Read the server's response
            String response = reader.readLine();
            System.out.println("Server says: " + response);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

How to run it:

  1. Start the Server first: Run SimpleTCPServer. It will sit and wait (“block”) at the accept() method.
  2. Start the Client: Run SimpleTCPClient. It will connect, send the message, and then both programs will finish.

Key Concepts:

  • ServerSocket: Used by the server to “listen” for incoming connection requests.
  • Socket: Represents the actual connection. Both the client and the server use a Socket object to talk to each other once the connection is established.
  • Try-with-resources: Using try (...) ensures that the sockets and streams are automatically closed, even if an error occurs.
  • Blocking: The accept() and readLine() methods are “blocking,” meaning the program pauses there until a connection is made or data is received.