TD de Programmation Orientée Objets
JDBC
Corrigé
dernière modification par Philippe.Genoud@imag.fr.
Pour télécharger les sources complets de la solution : CorrigeTPJDBCsrc.zip
Le programme DemoJDBC lit les paramètres de connexion dans un fichier "properties". Le nom de ce fichier properties est spécifié en argument de la ligne de commande au lancement du programme.
Le fichier de configuration contient les propriétés suivantes :
Exemple : fichier bdOracle.properties pour une connexion à Oracle sur hoff
# fichier de proprietés pour une connexion à la base Oracle ufrima sur hoff jdbcDriver=oracle.jdbc.driver.OracleDriver dataBaseUrl=jdbc:oracle:thin:@hoff.imag.fr:1521:ufrima userName=genoud passwd=****** |
Pour lancer le programme, ne pas oublier d'indiquer dans le classpath le fichier jar ou zip contenant les classes du driver. Ainsi pour exécuter le programme avec le fichier properties précédent on utilisera la commande suivante (en supposant que les classes du driver jdbc sont dans classes12.zip qui se trouve dans le même répertoire que l'application) :
Sous Windows java -cp .;classes12.zip DemoJDBC bdOracle.propertiesSous Unix : java -cp .:classes12.zip DemoJDBC bdOracle.properties
|
Source complet DemoJDBC.java |
1 import java.io.BufferedReader; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileReader; 6 import java.io.IOException; 7 import java.sql.Connection; 8 import java.sql.DriverManager; 9 import java.sql.PreparedStatement; 10 import java.sql.ResultSet; 11 import java.sql.ResultSetMetaData; 12 import java.sql.SQLException; 13 import java.sql.Statement; 14 import java.util.Properties; 15 import java.util.StringTokenizer; 16 17 18 /** 19 * Programme de démonstration de JDBC. 20 * Permet de se connecter à une BD Oracle et de tester différentes commandes SQL sur 21 * une table représentant les consommations de café de différents programmeurs. 22 * 23 * Les différentes opérations possibles sont : 24 * <OL> 25 * <LI>Créer la table</LI> 26 * <LI>Supprimer la table</LI> 27 * <LI>charger la table depuis un fichier</LI> 28 * <LI>Afficher le nom de la personne qui a consommé le plus de tasses de café en une 29 * journée ainsi que sa consommation ce jour là.</LI> 30 * <LI>Afficher le nombre total de tasses consommées.</LI> 31 * <LI>Afficher le nombre total de tasses consommées par un programmeur donné et 32 * le détail des consommations de celui-ci.</LI> 33 * <LI>Afficher les méta données concernant le résultat d"une requête quelconque</LI> 34 * <LI>Exécuter une requête quelconque saisie au clavier et afficher ses résultats</LI> 35 * </OL> 36 *<p> 37 * Les paramètres d"accès à la BD (classe du driver, url, nom d"utilisateur et mot de 38 * passe ) sont fixés dans un fichier properties spécifié en argument de la ligne de 39 * commande au lancement du programme. La forme de ce fichier est la suivante : 40 *</p> 41 *<pre> 42 * jdbcDriver=oracle.jdbc.driver.OracleDriver 43 * dataBaseUrl=jdbc:oracle:thin:@hoff.imag.fr:1521:ufrima 44 * userName=genoud 45 * passwd=xxxxxxxx 46 *</pres> 47 * @author Philippe Genoud (Philippe.Genoud@imag.fr) 48 */ 49 public class DemoJDBC { 50 51 private static Connection con; 52 private static Statement stmt; 53 54 /** 55 * Création de la table JoltData. La création n"a lieu que si la 56 * table JoltData n"existe pas encore. Sinon un message le signale 57 * sur la console. 58 */ 59 public static void creerTable() throws SQLException { 60 stmt.executeUpdate("create table JoltData ("+ 61 "programmer varchar (32),"+ 62 "day varchar (3),"+ 63 "cups integer)"); 64 System.out.println("table joltdata créée"); 65 } 66 67 /** 68 * initialisation de la table avec quelques valeurs 69 */ 70 public static void initTable() throws SQLException { 71 stmt.executeUpdate("INSERT INTO JoltData VALUES ("Gilbert", "Mon", 1)"); 72 stmt.executeUpdate("INSERT INTO JoltData VALUES ("Wally", "Mon", 2)"); 73 stmt.executeUpdate("INSERT INTO JoltData VALUES ("Edgar", "Tue", 8)"); 74 System.out.println("table joltdata supprimée"); 75 } 76 77 /** 78 * destruction de la table. 79 */ 80 public static void supprimerTable() throws SQLException { 81 stmt.executeUpdate("drop table JoltData"); 82 } 83 84 /** 85 * intialiasitation de la table JoltData à partir des données lues dans un fichier texte. 86 */ 87 public static void chargerBase() throws SQLException { 88 System.out.print("Nom du fichier : "); 89 String nomFichier = LectureClavier.lireChaine(); 90 BufferedReader fichierEntree = null; 91 try { 92 // ouverture du fichier 93 fichierEntree = new BufferedReader(new FileReader(nomFichier)); 94 95 PreparedStatement ps = con.prepareStatement("insert into JoltData values (?, ?, ?)"); 96 97 String ligneCour; // la ligne courante 98 99 while ((ligneCour = fichierEntree.readLine()) != null) { 100 // traitement de la ligne courrante. 101 // parcours des élements (tokens) de cette ligne avec un objet StringTokenizer 102 // classe définie dans java.util 103 StringTokenizer st = new StringTokenizer(ligneCour); 104 String nom = st.nextToken(); 105 String jour = st.nextToken(); 106 int nbc = Integer.parseInt(st.nextToken()); 107 ps.setString(1,nom); 108 ps.setString(2,jour); 109 ps.setInt(3,nbc); 110 ps.executeUpdate(); 111 112 } 113 114 ps.close(); 115 // fermeture du fichier 116 fichierEntree.close(); 117 } catch (IOException ioe) { 118 System.out.println("Erreur lecture dans le fichier" + nomFichier); 119 System.out.println(ioe.getMessage()); 120 121 } 122 } 123 124 /** 125 * Affiche le nom de la personne qui a consommé le plus de tasses de café en une journée ainsi 126 * que sa consommation ce jour là, puis la liste des personnes ordonnee par ordre décroissant 127 * du nombre de consommations. 128 * 129 */ 130 public static void nbreTassesMax() throws SQLException { 131 ResultSet rs = stmt.executeQuery("SELECT * FROM joltdata ORDER BY cups DESC"); 132 if ( rs.next()) { // pour accéder à la première ligne du ResultSet 133 // si celui-ci n"est pas vide 134 System.out.println("Le plus gros consommateur de café en une journée est : " + rs.getString(1)); 135 System.out.println("Sa plus grosse connsommation en une journée est : " + rs.getInt(3)); 136 System.out.println("Celle-ci a eu lieu : " + rs.getString(2)); 137 System.out.println(); 138 139 while (rs.next()) { // pour chaque ligne du result set 140 System.out.println(rs.getString(1) + ",\t" + // le nom 141 rs.getString(2) + ",\t" + // le jour 142 rs.getInt(3)); // la quantité 143 } 144 } 145 rs.close(); 146 147 } 148 149 /** 150 * affiche le nombre total de tasses consommées. 151 */ 152 public static void nbreTotalTasses() throws SQLException{ 153 ResultSet rs = stmt.executeQuery("SELECT SUM(cups) FROM joltdata"); 154 if (rs.next()) // pour accéder à la première ligne du ResultSet 155 // si celui-ci n"est pas vide 156 System.out.println("le nombre total de tasses consommées " + rs.getInt(1)); 157 else 158 System.out.println("la table est vide"); 159 rs.close(); 160 } 161 162 /** 163 * Renvoie le nombre total de tasses consommées par un programmeur donné et 164 * affiche le détail des consommations de celui-ci. 165 */ 166 public static void nbreTotalTassesPgm() throws SQLException { 167 System.out.print("nom du programmeur "); 168 String programmer = LectureClavier.lireChaine(); 169 ResultSet rs = stmt.executeQuery("SELECT day,cups FROM joltdata WHERE programmer="" 170 + programmer + """); 171 int nbt = 0; // le nombre total de tasses 172 int nbtj = 0; // le nombre de tasses par jour 173 while (rs.next() ) { 174 nbtj = rs.getInt("cups"); 175 System.out.println(rs.getString("day") + " : " + nbtj); 176 nbt += nbtj; 177 } 178 179 System.out.println("Le nombre total de tasses consommé par " + 180 programmer + " est " + nbt); 181 rs.close(); 182 183 } 184 185 /** 186 * Exécute une requête libre définie par une chaîne donnée au clavier et 187 * affiche les méta données concernant le résultat de cette requête 188 * quelconque.<BR> 189 * <UL> 190 * <LI>Si la command renvoie un ResultSet (Query) cette méthode indique : 191 * <UL> 192 * <LI>le nombre de colonnes, et pour chaque colonne le nom et le type 193 * de la colonne.</LI> 194 * <LI>le contenu du resultSet est affiché ligne par ligne sur la sortie 195 * standard.</LI> 196 * </UL> 197 * </LI> 198 * <LI>Si la commande ne renvoie pas un ResultSet (Update) cette méthode 199 * indique le nombre de lignes de la table qui ont été modifiées. 200 * <LI> 201 * </UL> 202 */ 203 public static void requeteLibreEtMetaDonnees() throws SQLException { 204 System.out.print("Rentrez votre requette :"); 205 String cmd = LectureClavier.lireChaine(); 206 207 if (stmt.execute(cmd)) { 208 ResultSet rs = stmt.getResultSet(); 209 210 // consultation et affichage des meta données 211 ResultSetMetaData rsmd = rs.getMetaData(); 212 int numberOfColumns = rsmd.getColumnCount(); 213 System.out.println("le résultat contient " + numberOfColumns + " colonnes");; 214 for (int i = 1; i <= numberOfColumns; i++) { 215 System.out.println("--------------------------------"); 216 System.out.println("Colonne : " + i + "\nNOM " + rsmd.getColumnName(i) 217 + " TYPE : " + rsmd.getColumnTypeName(i) ); 218 } 219 System.out.println("--------------------------------"); 220 221 //affichage du resutlat de la requête 222 System.out.println("Résultats de la requête\n"); 223 while (rs.next()) { 224 for (int i = 1; i <= numberOfColumns; i++) 225 System.out.print(rs.getString(i) + " "); 226 System.out.println(); 227 } 228 rs.close(); 229 } else { 230 System.out.println("Requête effectuée"); 231 System.out.println("Nombre de lignes modifiées " + stmt.getUpdateCount()); 232 } 233 } 234 235 /** 236 * affiche le menu présentant les différentes opérations possibles 237 */ 238 public static void affMenu() { 239 System.out.println("\n\n------------------------------------------"); 240 System.out.println("1 : Créer et initialiser la table"); 241 System.out.println("2 : Détruire la table"); 242 System.out.println("3 : Initaliser la table"); 243 System.out.println("4 : Consommation max (exo 2.1)"); 244 System.out.println("5 : Nombre total de tasses (exo 2.2)"); 245 System.out.println("6 : Nombre total tasses pour un programmeur (exo 2.3)"); 246 System.out.println("7 : Requete Libre et Méta données (exo 3)"); 247 System.out.println("8 : Charger les données depuis un fichier"); 248 System.out.println("0 : Quitter l"application"); 249 } 250 251 252 /** 253 * charge une classe de driver jdbc. Si le driver spécifié n"est pas trouvé l"exécution 254 * de l"application est interrompue. 255 * @param driver name le nom (Fully qulified Name) de la classe du driver. 256 */ 257 public static void chargerDriver(String driverName) { 258 // chargement du Driver Oracle 259 try { 260 Class.forName(driverName); 261 System.out.println("Driver " + driverName + "chargé"); 262 } catch (ClassNotFoundException e) { 263 System.out.println("erreur dans le chargement du driver"); 264 System.exit(0); 265 } 266 } 267 268 /** 269 * création d"une connexion. Si la connexion ne peut être créée l"application 270 * est interrompue. 271 * @param url l"url spécifiant la BD. 272 * @param username le nom de l"utilisateur 273 * @param passwd son mot de passe. 274 * @param return la ref de l"objet connexion créé. 275 */ 276 public static Connection ouvrirConnexion(String url, String username, String passwd) { 277 278 Connection con =null; 279 try { 280 con = DriverManager.getConnection( 281 url, 282 username, 283 passwd); 284 285 } catch (SQLException e) { 286 System.out.println("Impossible de se connecter à "+ url); 287 System.out.println("avec comme nom d"utilisateur : " + username); 288 System.out.println("et comme mot de passe " + passwd); 289 System.out.println(e.getMessage()); 290 System.exit(0); 291 } 292 return con; 293 } 294 295 public static void main(String[] args) { 296 297 int rep; // la réponse de l"utilisateur pour le menu principal 298 String propFileName = null; // le nom du fichier properties contenant les 299 // infos de connexion à la BD (classe du driver jdbc 300 // et url de connexion 301 302 if (args.length > 0) 303 propFileName = args[0]; 304 else { 305 System.out.println("usage : java DemoJDBC propertiesFile"); 306 System.exit(0); 307 } 308 309 // lecture des paramètres BD dans le fichier properties 310 311 Properties options = new Properties(); 312 try { 313 options.load(new FileInputStream(new File(propFileName))); 314 } 315 catch (FileNotFoundException fne) { 316 System.out.println("fichier " + propFileName + " non trouvé"); 317 System.exit(0); 318 } 319 catch (IOException ioe) { 320 System.out.println("problème lecture du ficher properties"); 321 System.exit(0); 322 } 323 324 String driverClassName = options.getProperty("jdbcDriver"); 325 String dataBaseUrl = options.getProperty("dataBaseUrl"); 326 String nom = options.getProperty("userName"); 327 String motDePasse = options.getProperty("passwd"); 328 329 // chargement du driver 330 chargerDriver(driverClassName); 331 332 // ouverture d"une connexion 333 con = ouvrirConnexion(dataBaseUrl,nom, motDePasse); 334 335 System.out.println("utilisateur " + nom + " connecté à " + dataBaseUrl); 336 337 //création d"un objet statement qui sera utilisé par toutes les 338 //opérations d"accès à la BD. Fermeture de la connexion et 339 // arrêt du programme en cas d"erreur 340 try { 341 stmt = con.createStatement(); 342 } catch (SQLException sqle) { 343 System.out.println("Problème à la création d"un Statement " + 344 sqle.getMessage()); 345 try { 346 con.close(); 347 } catch (SQLException e) { 348 e.printStackTrace(); // que faire de plus ? 349 } 350 System.exit(0); 351 } 352 353 do { 354 affMenu(); 355 System.out.print("votre choix : "); 356 357 358 rep = LectureClavier.lireEntier(); 359 System.out.println("\n\n"); 360 try { 361 switch (rep) { 362 case 0 : System.out.println("au revoir"); 363 break; 364 case 1 : creerTable(); 365 break; 366 case 2 : supprimerTable(); 367 break; 368 case 3 : initTable(); 369 break; 370 case 4 : nbreTassesMax(); 371 break; 372 case 5 : nbreTotalTasses(); 373 break; 374 case 6 : nbreTotalTassesPgm(); 375 break; 376 case 7 : requeteLibreEtMetaDonnees(); 377 break; 378 case 8 : chargerBase(); 379 break; 380 381 default: 382 System.out.println("valeur erronée !"); 383 } // end switch 384 } catch (SQLException sqle) { 385 System.out.println("Problème SQL\n" + sqle.getMessage()); 386 } catch (NumberFormatException nfe) { 387 System.out.println("\nsaisie incorrecte\n"); 388 } 389 } while (rep != 0); 390 391 // Fermer la connexion à la BD 392 try { 393 stmt.close(); 394 con.close(); 395 } catch (SQLException sqle) { 396 // que faire de plus ? 397 sqle.printStackTrace(); 398 } 399 } 400 401 } 402