Aller au menu - Aller au contenu

Icône Fouiller dans sa BDD

Mise à jour : 17/06/2009
Difficulté : Intermédiaire Intermédiaire Creative Commons BY-NC-SA
3 526 visites depuis 7 jours, dont 312 sur ce chapitre classé 45/786
Nous continuons notre voyage initiatique au pays de JDBC en abordant la manière d'interroger notre BDD.

Eh oui, une base de données n'est utile que si nous pouvons consulter, ajouter, modifier ou encore supprimer les données qu'elle comprend.

Par contre, pour faire ceci, il était IMPÉRATIF de se connecter. Mais vu que c'est chose faite, nous allons voir comment fouiner dans notre BDD.
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Le couple Statement - ResultSet

Voici deux objets que vous utiliserez sûrement beaucoup !
En fait, ce sont ces deux objets qui permettent de récupérer des données de la BDD ou de travailler avec celles-ci... :-°

Afin de vous faire comprendre tout ceci de façon simple, voici un exemple assez complet (mais pas trop quand même) affichant le contenu de la table classe :

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;

public class Connect {

	public static void main(String[] args) {
		
		try {
			Class.forName("org.postgresql.Driver");
			
			String url = "jdbc:postgresql://localhost:5432/Ecole";
			String user = "postgres";
			String passwd = "postgres";
			
			Connection conn = DriverManager.getConnection(url, user, passwd);
			
			//Création d'un objet Statement
			Statement state = conn.createStatement();
			//L'objet ResultSet contient le résultat de la requête SQL
			ResultSet result = state.executeQuery("SELECT * FROM classe");
			//On récupère les MetaData
			ResultSetMetaData resultMeta = result.getMetaData();
			
			System.out.println("\n**********************************");
			//On affiche le nom des colonnes
			for(int i = 1; i <=  resultMeta.getColumnCount(); i++)
				System.out.print("\t" + resultMeta.getColumnName(i).toUpperCase() + "\t *");
			
			System.out.println("\n**********************************");
			
			while(result.next()){			
				for(int i = 1; i <=  resultMeta.getColumnCount(); i++)
					System.out.print("\t" + result.getObject(i).toString() + "\t |");
				
				System.out.println("\n---------------------------------");

			}


                        result.close();
                        state.close();

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


Voici ce que nous donne ce code :

Image utilisateur


Vous avez sûrement compris que j'ai simplement exécuté une requête SQL et récupéré les lignes trouvées ! Mais détaillons un peu plus ce qu'il s'est passé. ^^

Déjà, vous aurez pu remarquer que j'ai spécifié l'URL complète pour la connexion : sinon comment voulez-vous savoir quelle BDD attaquer ?...

La connexion à la BDD mise à part, les choses se sont passées en quatre étapes distinctes :
  • création de l'objet Statement ;
  • exécution de la réquête SQL ;
  • récupération et affichage des données via l'objet ResultSet ;
  • fermeture des objets utilisés (bien que non obligatoire, c'est recommandé).


Tout ça semble clair, mais tu ne pourrais pas nous en dire un peu plus sur ces objets ?

Mais c'est ce que j'allais faire... ^^
Dîtes-vous une chose : objet Statement => instruction SQL ! C'est cet objet qui exécute les requêtes SQL et qui retourne les résultats.
Ensuite, lorsque vous entendez ResultSet, c'est que votre requête SQL a retourné un certain nombre de lignes à récupérer et à afficher...

Comment ça fonctionne

Je vous ai fourni un morceau de code, il fonctionne, mais comment ça marche ?
Voici le moment où tout vous sera dévoilé.

Comme je vous le disais plus haut, l'objet Statement est l'objet qui vous permet de faire des requêtes SQL. Celles-ci peuvent être de type :
  • CREATE ;
  • INSERT ;
  • UPDATE ;
  • SELECT ;
  • DELETE.

Vous n'êtes pas sans savoir que, selon le type de requête exécutée, celle-ci retourne un / des résultat(s), dans le cas d'un SELECT, ou une validation / un message d'erreur dans les autres cas.
L'objet Statement vous est fourni par l'objet Connection grâce à l'instruction conn.createStatement(); .
Nous verrons, dans le chapitre suivant, un peu plus de choses concernant l'objet Statement.


Ce que j'ai fait ensuite, c'est demander à mon objet Statement d'exécuter une requête SQL de type SELECT. Vous la voyez, celle-ci :

Code : SQL
1
SELECT * FROM classe


Cette requête me retournant un résultat contenant beaucoup de lignes, elles-mêmes contenant plusieurs colonnes, nous avons stocké ce résultat dans un objet ResultSet, objet permettant de faire diverses actions sur des résultats de requêtes SQL ! :)

Après cette ligne de code : ResultSet result = state.executeQuery("SELECT * FROM classe"); , les résultats sont stockés dans l'objet ResultSet et nous n'avons plus qu'à afficher les données.

Ici, j'ai utilisé un objet de type ResulSetMetaData afin de récupérer les "meta data" de ma requête. Comprenez ceci comme "récupérer les informations globales de ma requête". Ici, nous avons utilisé cet objet afin de récupérer le nombre de colonnes renvoyé par la requête SQL ainsi que leurs noms.
Cet objet "meta data" permettent de récupérer des informations très utiles comme :

  • le nombre de colonnes d'un résultat ;
  • le nom des colonnes d'un résultat ;
  • le type de données stocké dans chaque colonne ;
  • le nom de la table à qui appartient la colonne (dans le cas d'une jointure de table) ;
  • ...


Vous voyez que ces informations peuvent être utiles.
Il existe aussi un objet DatabaseMetaData qui, lui, fournit des informations sur la base de données !


Vous comprenez mieux ce que signifie cette portion de code :

Code : Java
1
2
3
4
5
6
System.out.println("\n**********************************");
//On affiche le nom des colonnes
for(int i = 1; i <=  resultMeta.getColumnCount(); i++)
	System.out.print("\t" + resultMeta.getColumnName(i).toUpperCase() + "\t *");
			
System.out.println("\n**********************************");


Nous nous servons de la méthode nous donnant le nombre de colonnes dans le résultat afin de récupérer le nom de la colonne grâce à son index !
ATTENTION : contrairement aux indices de tableaux, les indices de colonnes SQL commencent à 1 !


Ensuite, nous récupérons les données de notre requête en nous servant de l'indice des colonnes :

Code : Java
1
2
3
4
5
6
while(result.next()){			
	for(int i = 1; i <=  resultMeta.getColumnCount(); i++)
		System.out.print("\t" + result.getObject(i).toString() + "\t |");
				
	System.out.println("\n---------------------------------");
}


Nous utilisons une première boucle afin que, tant que notre objet ResultSet nous retourne des lignes de résultats, nous parcourions ensuite chaque ligne via notre boucle for .

La méthode next() permet de positionner l'objet sur la ligne suivante dans sa liste de résultat ! Au premier tour de boucle, cette méthode positionne l'objet sur la première ligne. Si vous ne positionnez pas l'objet résultat et que vous tentez de lire des données, une exception sera levée !


Je suis parti du postulat que ne connaissons pas le type de données de nos colonnes, mais vu que nous les connaissons, ce code aurait tout aussi bien fonctionné :

Code : Java
1
2
3
4
5
while(result.next()){
	System.out.print("\t" + result.getInt("cls_id") + "\t |");
	System.out.print("\t" + result.getString("cls_nom") + "\t |");
	System.out.println("\n---------------------------------");
}


On a le droit de faire ça ?

Tout à fait ! Nous connaissons le nom de nos colonnes retournées par la requête SQL, nous connaissons aussi leurs types, il nous suffit donc d'invoquer la méthode adéquat de l'objet ResultSet en utilisant le nom de la colonne à récupérer !
Par contre, si vous essayez de récupérer le contenu de la colonne "cls_nom" avec la méthode getInt("cls_nom") , vous aurez une zolie exception !


Il existe une méthode getXXX() par type primitif et quelques autres correspondant aux types SQL :

  • getArray(int colummnIndex) ;
  • getAscii(int colummnIndex) ;
  • getBigDecimal(int colummnIndex) ;
  • getBinary(int colummnIndex) ;
  • getBlob(int colummnIndex) ;
  • getBoolean(int colummnIndex) ;
  • getBytes(int colummnIndex) ;
  • getCharacter(int colummnIndex) ;
  • getDate(int colummnIndex) ;
  • getDouble(int colummnIndex) ;
  • getFloat(int colummnIndex) ;
  • getInt(int colummnIndex) ;
  • getLong(int colummnIndex) ;
  • getObject(int colummnIndex) ;
  • getString(int colummnIndex) ;


Et, à la fin, nous fermons nos objets :

Code : Java
1
2
result.close();
state.close();


Avant de voir plus en détail les possibilités qu'offrent ces objets, nous allons faire deux-trois requêtes SQL afin de nous habituer à la façon dont tout ça fonctionne ! ;)

Entraînons-nous

Le but du jeu est de me coder les résultats que j'ai obtenus... Je vous laisse chercher dans quelle table... :p
Vous êtes prêts ? C'est parti ! :ninja:

Voici ce que vous devez me récupérer en premier :

Image utilisateur


Cherchez bien...
Bon, vous avez trouvé ! Il n'y avait rien de compliqué ici, voici la correction, enfin, une suggestion de correction :

Secret (cliquez pour afficher)
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.sdz.exo;

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

public class Exo1 {

public static void main(String[] args) {
		
		try {
			Class.forName("org.postgresql.Driver");
			
			String url = "jdbc:postgresql://localhost:5432/Ecole";
			String user = "postgres";
			String passwd = "postgres";
			
			Connection conn = DriverManager.getConnection(url, user, passwd);
			Statement state = conn.createStatement();
			
			ResultSet result = state.executeQuery("SELECT * FROM professeur");
			ResultSetMetaData resultMeta = result.getMetaData();
			
			System.out.println("- Il y a " + resultMeta.getColumnCount() + " colonnes dans cette table");
			for(int i = 1; i <= resultMeta.getColumnCount(); i++)
				System.out.println("\t *" + resultMeta.getColumnName(i));
			

			System.out.println("Voici les noms et prénoms : ");
			System.out.println("\n---------------------------------");
			
			while(result.next()){
				System.out.print("\t" + result.getString("prof_nom") + "\t |");
				System.out.print("\t" + result.getString("prof_prenom") + "\t |");
				System.out.println("\n---------------------------------");
				
			}

                        result.close();
                        state.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
}



Allez, on complique la tâche :

Image utilisateur


Hou... Ne vous faites pas exploser la cervelle tout de suite... On ne fait que commencer... :p
Voici une possible solution à ce résultat :
Secret (cliquez pour afficher)

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.sdz.exo;

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

public class Exo2 {
	public static void main(String[] args) {
		
		try {
			Class.forName("org.postgresql.Driver");
			
			String url = "jdbc:postgresql://localhost:5432/Ecole";
			String user = "postgres";
			String passwd = "postgres";
			
			Connection conn = DriverManager.getConnection(url, user, passwd);
			Statement state = conn.createStatement();
			
			String query = "SELECT prof_nom, prof_prenom, mat_nom FROM professeur";
			query += " INNER JOIN j_mat_prof ON jmp_prof_k = prof_id";
			query += " INNER JOIN matiere ON jmp_mat_k = mat_id ORDER BY prof_nom";
			
			ResultSet result = state.executeQuery(query);
			String nom = "";
			
			while(result.next()){				
				if(!nom.equals(result.getString("prof_nom"))){
					nom = result.getString("prof_nom");
					System.out.println(nom + " " + result.getString("prof_prenom") + " enseigne : ");
				}
				System.out.println("\t\t\t - " +  result.getString("mat_nom"));
			}

                        result.close();
                        state.close();

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

}


Et le dernier pour la fin :

Image utilisateur

Secret (cliquez pour afficher)

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.sdz.exo;

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

public class Exo3 {
	public static void main(String[] args) {
		
		try {
			Class.forName("org.postgresql.Driver");
			
			String url = "jdbc:postgresql://localhost:5432/Ecole";
			String user = "postgres";
			String passwd = "postgres";
			
			Connection conn = DriverManager.getConnection(url, user, passwd);
			Statement state = conn.createStatement();
			
			String query = "SELECT prof_nom, prof_prenom, mat_nom, cls_nom FROM professeur";
			query += " INNER JOIN j_mat_prof ON jmp_prof_k = prof_id";
			query += " INNER JOIN matiere ON jmp_mat_k = mat_id";
			query += " INNER JOIN j_cls_jmp ON jcm_jmp_k = jmp_id";
			query += " INNER JOIN classe ON jcm_cls_k = cls_id AND cls_id IN(1, 7) ";
			query += " ORDER BY cls_nom DESC, prof_nom";
			
			ResultSet result = state.executeQuery(query);
			String nom = "";
			String nomClass = "";
			
			while(result.next()){				
				if(!nomClass.equals(result.getString("cls_nom"))){
					nomClass = result.getString("cls_nom");
					System.out.println("Classe de " + nomClass + " :");					
				}

				if(!nom.equals(result.getString("prof_nom"))){
					nom = result.getString("prof_nom");
					System.out.println("\t * " + nom + " " + result.getString("prof_prenom") + " enseigne : ");
				}
				System.out.println("\t\t\t - " +  result.getString("mat_nom"));
			}

                        result.close();
                        state.close();

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

}


Voilà : maintenant que vous vous êtes bien entraînés, nous allons approfondir un peu tout ceci... Mais avant, le QCM des familles. :diable:

Q.C.M.

Quel objet Java permet d'exécuter des requêtes SQL ?
Par quel biais récupère-t-on un objet Statement ?
Quel objet nous donne des informations sur la requête SQL exécutée ?
Quelle méthode de l'objet Statement permet d'exécuter une requête SQL ?
Ce code est-il correct ? (Partez du postulat que tout ce qui devrait être fait avant l'a été correctement.)


Code : Java
1
2
3
4
ResultSet result = state.executeQuery("SELECT * FROM classe");
System.out.print("\t" + result.getInt("cls_id") + "\t |");
System.out.print("\t" + result.getString("cls_nom") + "\t |");
System.out.println("\n---------------------------------");

Statistiques de réponses au QCM

C'est un chapitre riche mais pas trop compliqué...
Prenez le temps de voir comment le tout s'articule autour des Resultset et tutti quanti.

Les plus téméraires me retrouveront au prochain chapitre. :)
Chapitre précédent Sommaire Chapitre suivant

Partager

9 commentaires pour "Fouiller dans sa BDD"
Note moyenne : 3.34 / 4 (178 votes)
Pseudo Commentaire
Hors ligne bob1973 # Posté le 22/06/2010 à 14:20:16

Félicitations pour ce très bon tutoriel qui nous permet de gagner énormément de temps lorsqu'on souhaite démarrer sous java! :D

Je me permet de mettre ce commentaire pour les gens qui souhaiteraient utiliser mysql, puisque j'ai cherché un moment comment faire, donc ça peut interresser quelqu'un.

Personnellement, j'utilise EasyPHP qui contient un serveur apache + le serveur de bases de données MysQL. Du coup, par fainéantise, j'ai voulu tester si, comme le proposait 6boy, on pouvait réaliser les mêmes opérations avec Mysql au lieu de Postgresql (J'ai déjà des bases et des tables déjà remplies).

Première difficulté: où mettre l'archive ? :( Bêtement, j'ai cherché un moment car je croyais qu'il fallait le mettre dans lib/ext et je ne trouvais pas ce répertoire dans éclipse (et oui, je suis un vrai Zéro et je confonds encore JRE, JDK et autres JVM...).
Bon, c'était simple, il fallait regarder dans (sous windows): C:\Programmes\Java\jre6\lib\ext

Les vraies difficultés ont commencé après pour trouver quoi mettre dans le Class.forName("?????"); o_O
La solution: Class.forName("com.mysql.jdbc.Driver");

Pour l'url, même galère, donc au bout d'un moment j'ai trouvé: String url="jdbc:mysql://localhost:3306/xxxx";
xxxx représentant bien sûr le nom de la base utilisée.
Pour le numéro de port, j'ai mis celui-là car c'était celui qui était dans le fichier de configuration de Mysql sous EasyPHP, mais apparemment, cela fonctionne aussi sans le numéro de port.

Après, c'est du velours, le tutoriel de 6boy est magnifique, tout fonctionne parfaitement. :)

Voila en espérant que cela aidera d'autres Zéros...
Hors ligne Rossi # Posté le 30/08/2010 à 23:39:41

Salut tout le monde,
pouvez vous me dire la syntaxe de la requête d'insertion dans la table
merci
Hors ligne evanxg852000 # Posté le 29/10/2010 à 20:38:41
Avatar
Flux RSS

Bon tutorial, mais cette écriture n'est pas performante.
Code : Java
1
2
3
4
for(int i = 1; i <=  resultMeta.getColumnCount(); i++)
	System.out.print("\t" + resultMeta.getColumnName(i).toUpperCase() + "\t *");
			
System.out.println("\n**********************************");

L'appel d'une fonction ou méthode dans une initialisation de boucle for constitue un gros sacrifice de vitesse d'exécution.
Écrivez plutôt:
Code : Java
1
2
3
4
5
int nbTotal=resultMeta.getColumnCount();
for(int i = 1; i <= nbTotal ; i++)
	System.out.print("\t" + resultMeta.getColumnName(i).toUpperCase() + "\t *");
			
System.out.println("\n**********************************");

La framework Php le plus flexible et son IDE
Image utilisateur

 
Hors ligne Mirage34 # Posté le 15/02/2011 à 20:37:35

Bonjour CysBoy. Excellent ce tuto ainsi, que les autres. Néanmoins (comme c'est souvent le cas en matière d'exemple), ici, les programmes font références à :package com.sdz.prepare;
.
Hors, j'ai beau chercher sur le site et dans le texte, je ne trouve pas ce package. Comment faire ?

Merci
Hors ligne tatis2902 # Posté le 26/03/2011 à 00:41:32

Bonjour , merci pour ce tutoriel
svp , pourriez vous m'aider , je travaille sous netbeans6.9.1 et je voudrais faire la connexion à une base de données MySQL.
je suit le tutoriel , mais je ne sais ps ou est le problème .
merci d'avance .

Voir tous les commentaires