JDBC : **Java Database Connectivity**
Une **bibliothèque** du JDK pour interagir avec une **base de données relationnelle**.
Cette API générique permet de faire **des requêtes SQL** quel que soit le SGBD utilisé (ex. SQLite, PostgreSQL, MariaDb).
Documentation Javadoc du package `java.sql` : https://docs.oracle.com/en/java/javase/25/docs/api/java.sql/java/sql/package-summary.html
## Driver
```mermaid
flowchart TB
app[Application Java]
jdbc[API JDBC]
driver[Driver JDBC]
sqlite[SQLite]
postgres[PostgreSQL]
mariadb[MariaDB]
app---jdbc
jdbc---driver
driver ---- sqlite
driver ---- postgres
driver ---- mariadb
```
### Installation
Ajouter la dépendance d'un driver JDBC à votre projet
> [!example]- Driver SQlite
> Maven
> ```xml
> <dependency>
> <groupId>org.xerial</groupId>
> <artifactId>sqlite-jdbc</artifactId>
> <version>3.51.0.0</version>
> </dependency>
> ```
>
> Gradle (kotlin)
> ```kotlin
> dependencies {
> implementation("org.xerial:sqlite-jdbc:3.51.0.0")
> }
> ```
> [!example]- Driver MariaDB
> Maven
> ```xml
> <dependency>
> <groupId>org.mariadb.jdbc</groupId>
> <artifactId>mariadb-java-client</artifactId>
> <version>3.5.7</version>
> </dependency>
> ```
>
> Gradle (kotlin)
> ```kotlin
> dependencies {
> implementation("org.mariadb.jdbc:mariadb-java-client:3.5.7")
> }
> ```
> [!example]- Driver PostgreSQL
> Maven
> ```xml
> <dependency>
> <groupId>org.postgresql</groupId>
> <artifactId>postgresql</artifactId>
> <version>42.7.10</version>
> </dependency>
> ```
>
> Gradle (kotlin)
> ```kotlin
> dependencies {
> implementation("org.postgresql:postgresql:42.7.10")
> }
> ```
## Interagir avec une base de données depuis Java
1. Se connecter à une base de données (via le driver)
2. Créer une ou des requêtes SQL
3. Exécuter les requêtes
4. Récupérer et traiter les données
### Chaine de connexion JDBC
Une façon standardisée de codifier comment accéder à une base de données depuis JDBC.
```text
"jdbc:mysql://mysql.db.server:3306/my_database"
^ ^ ^ ^
| | | |
SGBD URL du serveur Port Base de données
```
### Créer une connexion à l'aide du `DriverManager`
```java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
```
Création d'une connexion à une base de données avec user et mot de passe.
```java
Connection connection = DriverManager.getConnection("jdbc:sqlite:test.db","user","password");
```
Création d'une connexion à une base de données sans mot de passe.
```java
Connection connection = DriverManager.getConnection(databaseUrl);
```
Exemple complet connexion à une base de données.
```java
String databaseUrl= "jdbc:sqlite:databasename.db";
try (Connection connection = DriverManager.getConnection(databaseUrl);
) {
// Faire des choses avec la connexion
} catch (SQLException e) {
System.err.println("Erreur lors de la connexion à la base de données : " + e.getMessage());
}
```
### Exécuter une requête
A partir d'une `Connection` **ouverte**.
De façon simplifiée :
```java
Statement stmt = connection.createStatement();
String query = "SELECT id, name FROM customer";
ResultSet rs = stmt.executeQuery (query) ;
rs.close() // ResultSet est AutoCloseable
stmt.close() // Statement est AutoCloseable
connection.close(); // Connection est AutoCloseable
```
Les imports nécessaires
```java
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
```
Exemple plus détaillé
```java
try (Statement statement = connection.createStatement() ) {
String query = """
SELECT id, name
FROM customer
""";
try (ResultSet resultSet = statement.executeQuery(query) ) {
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
// Faire quelque chose avec ces données
}
}
} catch (SQLException e) {
// Gérer l'erreur comme il se doit
}
```
### Correspondance des types Java et Sql
![[image-35.png|320x392]]
### Requêtes dynamiques et injection SQL
> [!danger] Il ne faut pas écrire des requêtes dynamiques par concaténation de texte
> ```java
> String name = "Voldemort";
> String query = "SELECT id, name FROM customer WHERE name='" + name +"'";
> ```
Cela est une **faille de sécurité critique** qui rend votre application vulnérable aux **injections SQL**.
En gros, vous permettez à un attaquant de contrôler votre base de données si vous n'assainissez pas vos requêtes SQL.
JDBC propose un système de **requêtes préparées** pour assainir vos requêtes.
#### Requêtes préparées
Une requête préparée est une requête qui contient **des paramètres** à fournir pour son exécution
Elle sert en général à effectuer des concaténations dans une requête SQL
```java
String query = " SELECT * FROM employees INNER JOIN "
+ " offices ON employees.officeCode = offices.officeCode "
+ " WHERE offices.country =? " // 1
+ " AND employees. lastName = ? "; // 2
try (PreparedStatement statement = connection.prepareStatement(query)) {
statement.setString(1, "USA");
statement.setString(2, "Murphy");
ResultSet rs = statement.executeQuery();
// traiter les données
}
```
## À suivre
[[Stream API]]