Vous avez appris un tas de choses sur JDBC et il est grand temps que vous les mettiez en pratique !
Dans ce TP, je vais vous demander de réaliser un testeur de requêtes SQL. Vous ne voyez pas où je veux en venir ? Lisez donc la suite…
Cahier des charges
Voici ce que j’attends de vous :
- créer une IHM permettant la saisie d’une requête SQL dans un champ ;
- lancer l’exécution de la requête grâce à un bouton se trouvant dans une barre d’outils ;
- si la requête renvoie 0 ou plusieurs résultats, les afficher dans un
JTable
; - le nom des colonnes devra être visible ;
- en cas d’erreur, un pop-up (
JOptionPane
) contenant le message s’affichera ; - un petit message en bas de fenêtre affichera le temps d’exécution de la requête ainsi que le nombre de lignes retournées.
Voilà : vous avez de quoi faire !
Si vous ne savez pas comment procéder pour le temps d’exécution de la requête, voici un indice : System.currentTimeMillis()
retourne un long
…
Quelques captures d'écran
Les figures suivantes vous montrent ce que j’ai obtenu avec mon code. Inspirez-vous-en pour réaliser votre programme.



Je n’ai plus qu’à vous souhaiter bonne chance et bon courage ! Let’s go !
Correction
Classe SdzConnection.java
package com.sdz.connection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JOptionPane;
public class SdzConnection{
/**
* URL de connection
*/
private static String url = "jdbc:postgresql://localhost:5432/Ecole";
/**
* Nom du user
*/
private static String user = "postgres";
/**
* Mot de passe du user
*/
private static String passwd = "postgres";
/**
* Objet Connection
*/
private static Connection connect;
/**
* Méthode qui va retourner notre instance
* et la créer si elle n'existe pas...
* @return
*/
public static Connection getInstance(){
if(connect == null){
try {
connect = DriverManager.getConnection(url, user, passwd);
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getMessage(), "ERREUR DE CONNEXION ! ", JOptionPane.ERROR_MESSAGE);
}
}
return connect;
}
}
Classe Fenetre.java
package com.sdz.tp;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import com.sdz.connection.SdzConnection;
public class Fenetre extends JFrame {
/**
* ToolBar pour le lancement des requêtes
*/
private JToolBar tool = new JToolBar();
/**
* Le bouton
*/
private JButton load = new JButton(new ImageIcon("img/load.png"));
/**
* Le délimiteur
*/
private JSplitPane split;
/**
* Le conteneur de résultat
*/
private JPanel result = new JPanel();
/**
* Requête par défaut pour le démarrage
*/
private String requete = "SELECT * FROM classe";
/**
* Le composant dans lequel taper la requête
*/
private JTextArea text = new JTextArea(requete);
/**
* Constructeur
*/
public Fenetre(){
setSize(900, 600);
setTitle("TP JDBC");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
initToolbar();
initContent();
initTable(requete);
}
/**
* Initialise la toolbar
*/
private void initToolbar(){
load.setPreferredSize(new Dimension(30, 35));
load.setBorder(null);
load.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event){
initTable(text.getText());
}
});
tool.add(load);
getContentPane().add(tool, BorderLayout.NORTH);
}
/**
* Initialise le contenu de la fenêtre
*/
public void initContent(){
//Vous connaissez ça...
result.setLayout(new BorderLayout());
split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(text), result);
split.setDividerLocation(100);
getContentPane().add(split, BorderLayout.CENTER);
}
/**
* Initialise le visuel avec la requête saisie dans l'éditeur
* @param query
*/
public void initTable(String query){
try {
//On crée un statement
long start = System.currentTimeMillis();
Statement state = SdzConnection.getInstance().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
//On exécute la requête
ResultSet res = state.executeQuery(query);
//Temps d'exécution
//On récupère les meta afin de récupérer le nom des colonnes
ResultSetMetaData meta = res.getMetaData();
//On initialise un tableau d'Object pour les en-têtes du tableau
Object[] column = new Object[meta.getColumnCount()];
for(int i = 1 ; i <= meta.getColumnCount(); i++)
column[i-1] = meta.getColumnName(i);
//Petite manipulation pour obtenir le nombre de lignes
res.last();
int rowCount = res.getRow();
Object[][] data = new Object[res.getRow()][meta.getColumnCount()];
//On revient au départ
res.beforeFirst();
int j = 1;
//On remplit le tableau d'Object[][]
while(res.next()){
for(int i = 1 ; i <= meta.getColumnCount(); i++)
data[j-1][i-1] = res.getObject(i);
j++;
}
//On ferme le tout
res.close();
state.close();
long totalTime = System.currentTimeMillis() - start;
//On enlève le contenu de notre conteneur
result.removeAll();
//On y ajoute un JTable
result.add(new JScrollPane(new JTable(data, column)), BorderLayout.CENTER);
result.add(new JLabel("La requête à été exécuter en " + totalTime + " ms et a retourné " + rowCount + " ligne(s)"), BorderLayout.SOUTH);
//On force la mise à jour de l'affichage
result.revalidate();
} catch (SQLException e) {
//Dans le cas d'une exception, on affiche une pop-up et on efface le contenu
result.removeAll();
result.add(new JScrollPane(new JTable()), BorderLayout.CENTER);
result.revalidate();
JOptionPane.showMessageDialog(null, e.getMessage(), "ERREUR ! ", JOptionPane.ERROR_MESSAGE);
}
}
/**
* Point de départ du programme
* @param args
*/
public static void main(String[] args){
Fenetre fen = new Fenetre();
fen.setVisible(true);
}
}
Bien sûr, ce code n’est pas parfait, vous pouvez l’améliorer ! Voilà d’ailleurs quelques pistes :
- vous pouvez utiliser un autre composant que moi pour la saisie de la requête, par exemple un
JTextPane
pour la coloration syntaxique ; - vous pouvez également créer un menu qui vous permettra de sauvegarder vos requêtes ;
- vous pouvez également créer un tableau interactif autorisant la modification des données.
Bref, ce ne sont pas les améliorations qui manquent !