# JDBC

## About

**JDBC** stands for **Java Database Connectivity**. It is an **API (Application Programming Interface)** provided by Java that enables Java applications to interact with databases. JDBC allows Java programs to execute SQL statements, retrieve results, and manage database connections in a standardized way.

It is a part of the **Java Standard Edition (Java SE)** and acts as a bridge between a Java application and various relational database management systems (RDBMS).

{% hint style="success" %}

### Why JDBC?

Before JDBC, Java applications relied on vendor-specific database APIs which lacked portability. JDBC was introduced by Sun Microsystems (now Oracle) to provide a **database-independent** interface for Java applications, allowing them to interact with any database that supports JDBC-compliant drivers.
{% endhint %}

{% hint style="success" %}
**Is JDBC only for SQL?**\
\
JDBC is primarily designed for relational (SQL) databases, not for NoSQL databases.

JDBC is for **SQL-based relational databases** such as: MySQL, PostgreSQL, Oracle DB, Microsoft SQL Server, SQLite, DB2, H2, etc.

JDBC is Not Meant for **NoSQL databases**, such as: MongoDB, Cassandra, Redis, Neo4j, Couchbase, DynamoDB\ <br>

**Can We Use JDBC with NoSQL?**

In some cases, Yes, via special JDBC wrappers or drivers provided by vendors.

Examples:

* **MongoDB JDBC Driver** – Wraps MongoDB's query interface and exposes it in a JDBC-like way.
* **Cassandra JDBC Driver** – Provided by third parties for tools like BI dashboards that require JDBC.

However, these are:

* Limited in capability
* Not standardized
* Often used only to enable JDBC-based tools like Apache Spark, Tableau, or BI reporting tools to read NoSQL data.
  {% endhint %}

## Goals of JDBC

* Provide a standard interface for accessing relational databases.
* Enable platform-independent database access.
* Allow developers to execute SQL queries and updates from Java.
* Support database transactions.
* Allow metadata retrieval (e.g., information about database structure).

## Features of JDBC

### 1. Database Connectivity Using Standard Java APIs

JDBC provides a **standardized interface** for Java applications to interact with a wide variety of relational databases. Developers do not need to learn the specific API for each database; instead, they can use the consistent set of JDBC interfaces and classes. This allows applications to remain **portable and database-independent**, making it easier to switch between databases (e.g., from MySQL to PostgreSQL) with minimal changes in code, provided the appropriate driver is available.

> JDBC abstracts the complexity of low-level database communication by offering familiar and consistent object-oriented programming constructs.

### 2. Execution of SQL Queries and Updates

JDBC enables Java applications to execute **SQL commands** directly, which include:

* **Queries** (`SELECT`) to retrieve data.
* **Updates** (`INSERT`, `UPDATE`, `DELETE`) to modify data.
* **DDL statements** (`CREATE TABLE`, `ALTER TABLE`, etc.) to manage database structure.

Developers can execute SQL using `Statement`, `PreparedStatement`, and `CallableStatement` interfaces. The results of queries are returned via `ResultSet` objects, allowing for easy traversal and data extraction.

> JDBC gives direct control over SQL execution, enabling the developer to use native SQL features supported by the database.

### 3. Support for Both Static and Dynamic SQL

* **Static SQL** refers to SQL queries that are fixed and hard-coded into the program. These are executed using the `Statement` interface.

  ```java
  Statement stmt = conn.createStatement();
  ResultSet rs = stmt.executeQuery("SELECT * FROM employees");
  ```
* **Dynamic SQL** is generated at runtime and often uses placeholders (`?`) for parameters. These are supported via `PreparedStatement`, allowing safer and more flexible query execution.

  ```java
  PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM employees WHERE department = ?");
  pstmt.setString(1, "HR");
  ```

> Dynamic SQL makes the application **more flexible and secure**, particularly in preventing SQL injection attacks.

### 4. Transaction Management

JDBC provides **manual transaction control** for managing atomic operations. This is critical for **data integrity and consistency**. By default, JDBC uses **auto-commit mode**, where every SQL statement is committed immediately. Developers can disable this and group multiple operations into a single transaction.

```java
conn.setAutoCommit(false);
// Execute multiple queries
conn.commit(); // or conn.rollback();
```

> Transactions ensure that a series of operations either **complete entirely or not at all**, adhering to the **ACID** properties of databases.

### 5. Exception Handling via SQLException

All database-related errors in JDBC are handled using the `SQLException` class. It provides detailed information such as:

* **Error message**
* **SQL state**
* **Vendor-specific error code**
* **Chained exceptions**

Example:

```java
try {
    // JDBC logic
} catch (SQLException e) {
    System.out.println("Error: " + e.getMessage());
}
```

> This structured error handling makes it easier to debug and manage different types of database-related issues programmatically.

### 6. Metadata Access Through DatabaseMetaData and ResultSetMetaData

JDBC provides access to **metadata**—data about the database structure and query results:

* `DatabaseMetaData`: Used to retrieve information about the database such as table names, supported SQL features, driver details, and more.
* `ResultSetMetaData`: Provides details about the columns in a result set, such as column name, type, and size.

Example:

```java
DatabaseMetaData dbMeta = conn.getMetaData();
ResultSetMetaData rsMeta = rs.getMetaData();
```

> Metadata access is useful for building **dynamic queries**, **auto-generating reports**, or working with unknown schemas at runtime.

### 7. Batch Processing for Performance Optimization

JDBC supports batch processing, which allows grouping multiple SQL commands into a **single batch** and executing them together. This reduces **network round-trips** and improves performance, especially for operations like inserting large volumes of data.

```java
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users (name) VALUES (?)");
for (String name : nameList) {
    pstmt.setString(1, name);
    pstmt.addBatch();
}
pstmt.executeBatch();
```

> Batch execution can lead to **significant performance gains**, especially when interacting with large datasets or performing bulk inserts/updates.

### 8. Support for Stored Procedures

JDBC supports calling **stored procedures** using the `CallableStatement` interface. Stored procedures are precompiled SQL routines stored in the database, often used for:

* Reusability
* Performance optimization
* Business logic encapsulation

Example:

```java
CallableStatement cs = conn.prepareCall("{call get_employee_details(?)}");
cs.setInt(1, 101);
ResultSet rs = cs.executeQuery();
```

> Stored procedure support allows complex operations to be offloaded to the database, reducing Java application complexity and improving execution speed.

## JDBC Architecture

The JDBC architecture consists of two main layers:

1. JDBC API Layer (Application Layer)
2. JDBC Driver Layer (Communication Layer)

### 1. JDBC API Layer (Application Layer)

This is the **upper layer** of the JDBC architecture. It is part of the **Java Standard Edition API** and provides a set of **interfaces and classes** that Java developers use directly in their applications.

#### **Responsibilities**

* Acts as a bridge between Java applications and the database drivers.
* Exposes standardized APIs for operations like connecting to databases, executing SQL queries, managing transactions, and processing results.
* Provides abstraction so developers do not need to worry about database-specific implementations.

#### **Core Interfaces/Classes**

* **`DriverManager`**: Loads and manages JDBC drivers. It chooses the appropriate driver for a given database URL.
* **`Connection`**: Represents a session with the database. Used to manage transactions and execute statements.
* **`Statement`**, **`PreparedStatement`**, **`CallableStatement`**: Used to send SQL commands to the database.
* **`ResultSet`**: Provides access to query results.
* **`SQLException`**: Used for handling errors and exceptions.
* **`DatabaseMetaData`**, **`ResultSetMetaData`**: Provide metadata about the database and result sets.

#### **Benefits of JDBC API Layer**

* **Database independence**: Applications can switch databases without rewriting code.
* **Standardized programming**: Developers use a consistent API across all supported databases.
* **Fine-grained control**: Gives the programmer control over SQL and JDBC operations.

#### **Example Flow**

1. The application calls `DriverManager.getConnection(...)`.
2. A `Connection` object is returned.
3. The application creates a `Statement` or `PreparedStatement`.
4. SQL queries are sent via this statement.
5. The results are captured using a `ResultSet`.

### 2. JDBC Driver Layer (Communication Layer)

This is the **lower layer** of the JDBC architecture and contains the actual **JDBC driver** implementation that communicates directly with the **database**.

#### **Responsibilities**

* Translates the JDBC API calls into **database-specific** calls (usually in native code or via protocol).
* Handles all interactions with the database server, including:
  * Establishing network connections
  * Sending SQL queries
  * Receiving results
  * Handling database errors

#### **How It Works**

* When a JDBC call is made from the application, the call is passed to the **DriverManager**, which identifies the correct JDBC driver.
* The driver then translates the JDBC calls into **database-native protocol commands**.
* The driver sends these commands to the database and returns the results back to the JDBC API layer.

#### **Benefits of JDBC Driver Layer**

* **Database-specific optimizations**: Each driver is optimized for the target RDBMS.
* **Decoupling**: Java applications don't need to include DB-specific logic.
* **Plug-and-play**: Drivers can be swapped to change or upgrade the database backend.

## Types of JDBC Drivers

JDBC drivers act as translators between a Java application and the database. They convert Java calls (JDBC API calls) into database-specific calls.

There are **four types of JDBC drivers**, classified based on how they communicate with the database.

### Type 1: JDBC-ODBC Bridge Driver

This driver uses the **ODBC (Open Database Connectivity)** driver to connect to the database. It translates JDBC method calls into ODBC function calls and relies on a native ODBC driver provided by the database vendor.

#### **Architecture**

```
Java Application → JDBC API → JDBC-ODBC Bridge → ODBC Driver → Database
```

#### Requirements

* `odbc32.dll` (Windows)
* ODBC driver installed and configured

#### Advantages

* Allows connectivity to any database that supports ODBC.
* Good for **quick prototyping** and **testing**.

#### Disadvantages

* Platform-dependent (usually Windows).
* Slower performance due to multiple layer translations.
* Not suitable for production.
* Deprecated since JDK 8 and removed in newer versions.

#### Use Cases

* Only suitable for **legacy applications** or **early JDBC experimentation**.

### Type 2: Native-API Driver (Partially Java Driver)

This driver converts JDBC calls into native C/C++ calls specific to the database API using JNI (Java Native Interface). It requires **database vendor-specific native libraries**.

#### Architecture

```
Java Application → JDBC API → Native-API Driver (JNI) → Native DB Client → Database
```

#### Requirements

* Native database client software must be installed on the client machine.
* JNI configuration needed.

#### Advantages

* Better performance than Type 1.
* Allows access to **proprietary features** of the database.

#### Disadvantages

* **Platform-dependent** (native code).
* Requires **extra setup** (install native libraries).
* Harder to deploy and maintain across platforms.
* Cannot be used in **web-based applications** easily.

#### Use Cases

* Useful when **native DB client is already required**.
* Not recommended for enterprise web applications.

### Type 3: Network Protocol Driver (Middleware Driver)

This driver uses a **middleware server** to convert JDBC calls into the database protocol. The Java client communicates with the middleware via **a vendor-specific network protocol**.

#### Architecture

```
Java Application → JDBC API → Type 3 Driver → Middleware Server → Database
```

#### Middleware

The middleware component handles:

* Load balancing
* Connection pooling
* Security
* Data translation

#### Advantages

* **Platform-independent** (no native code).
* Can connect to **multiple databases** using a single driver.
* Good for **internet-based applications**.

#### Disadvantages

* Requires **middleware server** installation and maintenance.
* More **complex architecture** than Type 4.
* Potential **network latency**.

#### Use Cases

* Suitable for **multi-tier enterprise applications**.
* Good for **centralized access** to different databases.

### Type 4: Thin Driver (Pure Java Driver)

This is the most widely used driver. It directly converts JDBC calls into the **native protocol of the database**, without needing any middleware or native libraries. It is written entirely in Java.

#### Architecture

```
Java Application → JDBC API → Type 4 Driver → Database
```

#### Examples

* MySQL: `com.mysql.cj.jdbc.Driver`
* PostgreSQL: `org.postgresql.Driver`
* Oracle: `oracle.jdbc.OracleDriver`

#### Advantages

* 100% Java, hence platform-independent.
* Best performance and portability.
* Easy to deploy—only need the JAR file.
* Well-supported by modern databases and frameworks.

#### Disadvantages

* Each database requires its own Type 4 driver.
* Vendor-specific optimizations may lead to slight incompatibility.

#### Use Cases

Recommended for most applications, including: Desktop apps, Web apps, Spring Boot applications, Microservices, Cloud deployments

### Comparison

<table data-full-width="true"><thead><tr><th width="84.4609375">Driver Type</th><th width="220.80078125">Translation Method</th><th>Platform Dependent</th><th width="137.40625">Middleware Required</th><th>Performance</th><th>Usage Today</th></tr></thead><tbody><tr><td>Type 1</td><td>JDBC → ODBC</td><td>Yes</td><td>No</td><td>Low</td><td>Deprecated</td></tr><tr><td>Type 2</td><td>JDBC → Native API</td><td>Yes</td><td>No</td><td>Moderate</td><td>Rare</td></tr><tr><td>Type 3</td><td>JDBC → Middleware → DB</td><td>No</td><td>Yes</td><td>Moderate</td><td>Rare</td></tr><tr><td>Type 4</td><td>JDBC → DB Protocol</td><td>No</td><td>No</td><td>High</td><td>Common</td></tr></tbody></table>

### JDBC vs ORM (like JPA/Hibernate)

| Feature        | JDBC                        | ORM (e.g., JPA/Hibernate) |
| -------------- | --------------------------- | ------------------------- |
| Mapping        | Manual                      | Automatic                 |
| SQL Writing    | Required                    | Optional (auto-generated) |
| Code Length    | Verbose                     | Concise                   |
| Learning Curve | Lower initially             | Higher initially          |
| Flexibility    | High                        | Moderate                  |
| Abstraction    | Low                         | High                      |
| Maintenance    | Tedious for large codebases | Easier                    |
