Outils de développement Informatique

JDBC

kn@lri.fr

Modèle avec JDBC

Utilité d'une base de données ?

Une base de données de films

On se place dans le cadre d'une application permettant d'accéder à une base de données de films. Le schéma logique de la base est représenté par le diagramme UML suivant :

  • Un film peut avoir plusieurs réalisateurs, et au moins un;
  • Un film a au moins un « acteur ». Un acteur est composé d'un rôle pour ce film et d'une personne. Attention, le Role de Luke Skywalker est différent pour les films Starwars IV, V, VI (même si c'est le même acteur et le même nom de rôle).

Encodage « naturel » en SQL (1/2)

CREATE TABLE PEOPLE (pid INTEGER, firstname VARCHAR(30), lastname VARCHAR(30), PRIMARY KEY(pid)); CREATE TABLE MOVIE (mid INTEGER, title VARCHAR(90) NOT NULL, year INTEGER NOT NULL, runtime INTEGER NOT NULL, rank INTEGER NOT NULL, PRIMARY KEY (mid)); CREATE TABLE ROLE (mid INTEGER, pid INTEGER, name VARCHAR(70), PRIMARY KEY(mid, pid, name), FOREIGN KEY (mid) REFERENCES MOVIE, FOREIGN KEY (pid) REFERENCES PEOPLE); CREATE TABLE DIRECTOR (mid INTEGER, pid INTEGER, PRIMARY KEY (mid, pid), FOREIGN KEY (mid) REFERENCES MOVIE, FOREIGN KEY (pid) REFERENCES PEOPLE);

Encodage « naturel » en SQL (2/2)

  • entités ⟹ tables de données
  • relations ⟹ tables de jointure & contraintes de clé
  • (économie d'une table de données pour ROLE.name)

Remarque

Ici on veut faire une mini-application simplifiée pour rechercher toutes les personnes qui contiennent une chaîne donnée dans leur nom, trié par ordre alphabétique.

Création du modèle

On va créer deux classes Java pour le modèle :

Person
Une classe représentant une personne, avec son nom et son prénom
PersonDB
Une classe encapsulant la connexion à la base et permettant de renvoyer l'ensemble (Java) de toutes les personnes de la base ayant une certaine chaîne dans son nom.
public class Person { private final String firstname; private final String lastname; public Person(String f, String l) { this.firstname = f; this.lastname = l; } public String getFirstname() { return firstname; } public String getLastname() { return lastname; } }

Classe Person

  • Doit être publique
  • Doit posséder des getter publiques pour les attributs qu'on veut afficher dans la vue

Le getter pour une propriété foo est une méthode publique getFoo()

Classe PersonDB et rappels JDBC

public class PersonDB { Connection cnx; public PersonDB() { Class.forName("org.postgresql.Driver"); cnx = DriverManager.getConnection("jdbc:postgresql://host:port/base", "username", "password"); } public List<Person> getPeople (String s) throws SQLException { List<Person> res = new ArrayList<>(); Statement st = cnx.createStatement(); ResultSet r = st.executeQuery("SELECT * FROM PEOPLE " + " WHERE LASTNAME LIKE " + " '%" + s + "%'"); while (r.next()) { res.add(new Person<>(r.getString("FIRSTNAME"), r.getString("LASTNAME"))); } return res; } }

Connexion à une base

Class.forName("org.postgresql.Driver"); connection = DriverManager.getConnection("jdbc:postgresql://host:port/" + base, username, password);
  • On importe dans la JVM courante le classe qui code le driver vers une base de donnée (ici Postgresql)
  • Le code de cette classe doit se trouver dans un .jar ou .class accessible depuis le CLASSPATH
  • La classe DriverManager maintient une Map entre chaîne de caractères ("jdbc:postgresql") et classe (org.postgresql.Driver)
  • La méthode getConnection utilise le préfixe de l'URL de connexion pour savoir quel driver utiliser.

Exécution de requêtes

  • On crée un objet Statement
  • L'évaluation d'une requête se fait via executeQuery sur le Statement.
  • Un ResultSet implémente une interface d'itérateur, initialement positionné avant la première ligne de résultats.
  • La méthode next avance dans l'itérateur et renvoie vrai tant qu'on est sur un résultat.
  • On accède à la colonne voulue avec getType. On doit donner le type Java correspondant au type SQL de la colonne. On peut accéder aux colonnes par numéro (à partir de 1) ou par nom.

Éxécution de mises à jour

public boolean deleteDirectorById (int id) throws SQLException { Statement st = cnx.createStatement(); int r = st.executeUpdate("DELETE FROM DIRECTOR WHERE pid =" + id ); return r != 0; } }

Syntaxe SQL (en 1 slide)

-- Requête SELECT … FROM T1, T2, ... WHERE condition; SELECT … FROM T1, T2, ... WHERE condition ORDER BY x; -- Insertion INSERT INTO T VALUES(v1, v2, ...); -- Mise à jour UPDATE T SET col1 = v1, col2 = v2, ... WHERE condition; -- SUPPRESSION DELETE FROM T WHERE condition; -- CREATION DE TABLE CREATE TABLE T (col1 typ1, col2 typ2, ...) -- DESTRUCTION DE TABLE DROP TABLE T;