t
t
t
t
t t 15) Informatique distribuée
tttt
15) Informatique distribuée
Texte original t Traducteur : Jean-Pierre VIDAL, Alban PEIGNIER
t
t
///
Ce chapitre contient 12 pages
1 2 3 4 5 6 7 8 9 10 11 12
\\\
t t t
t t t
t
t t t
The JabberClientThread constructor takes an InetAddress and uses it to open a Socket. You’re probably starting to see the pattern: the Socket is always used to create some kind of Reader and/or Writer (or InputStream and/or OutputStream) object, which is the only way that the Socket can be used. (You can, of course, write a class or two to automate this process instead of doing all the typing if it becomes painful.) Again, start( ) performs thread initialization and calls run( ). Here, messages are sent to the server and information from the server is echoed to the screen. However, the thread has a limited lifetime and eventually completes. Note that the socket is cleaned up if the constructor fails after the socket is created but before the constructor completes. Otherwise the responsibility for calling close( ) for the socket is relegated to the run( ) method. t Le constructeur de JabberClientThread prend une InetAddress afin d'ouvrir un Socket. Vous devinez sans doute la suite : Socket est utilisé pour créer un objet du type Readeret/ou Writer (ou bien InputStream et/ou OutputStream), ce qui est la seule manière d'utiliser un Socket (bien entendu on peut écrire une classe ou deux afin d'automatiser ce travail au lieu de tout retaper à chaque fois, si cela devient trop pénible). À nouveau, start( ) initialise le thread puis appelle run( ). A ce point, des messages sont envoyés au serveur et l'information en retour du serveur est affichée en écho sur l'écran. Toutefois, la durée de vie du thread est limitée et finalement il se termine. Remarquons que la socket est nettoyée si le constructeur échoue après que la socket soit créée mais avant que l'exécution du constructeur soit terminée. Dans les autres cas la responsabilité d'appeler la méthode close( ) de socket est déléguée à la méthode run( ).
t t t
The threadcount keeps track of how many JabberClientThread objects currently exist. It is incremented as part of the constructor and decremented as run( ) exits (which means the thread is terminating). In MultiJabberClient.main( ), you can see that the number of threads is tested, and if there are too many, no more are created. Then the method sleeps. This way, some threads will eventually terminate and more can be created. You can experiment with MAX_THREADS to see where your particular system begins to have trouble with too many connections. t La variable threadCount garde la trace du nombre de JabberClientThread existant actuellement. Elle est incrémentée dans le constructeur et décrémentée lorsque run( ) termine (ce qui signifie que le thread est en train de se terminer). Dans MultiJabberClient.main( ) le nombre de threads est testé, on arrête d'en créer s'il y en a trop. Dans ce cas la méthode s'endort. De cette manière, certains threads peuvent se terminer et de nouveaux pourront être créés. Vous pouvez faire l'expérience, en changeant la valeur de MAX_THREADS, afin de savoir à partir de quel nombre de connexions votre système commence à avoir des problèmes.
t t t

Datagrams

t

Les Datagrammes

t t t
The examples you’ve seen so far use the Transmission Control Protocol (TCP, also known as stream-based sockets), which is designed for ultimate reliability and guarantees that the data will get there. It allows retransmission of lost data, it provides multiple paths through different routers in case one goes down, and bytes are delivered in the order they are sent. All this control and reliability comes at a cost: TCP has a high overhead. t Les exemples que nous venons de voir utilisent le Protocole de Contrôle de Transmission Transmission Control Protocol (TCP, connu également sous le nom de stream-based sockets- sockets basés sur les flux, NdT), qui est conçu pour une sécurité maximale et qui garantit que les données ne seront pas perdues. Il permet la retransmission des données perdues, il fournit plusieurs chemins au travers des différents routeurs au cas où l'un d'eux tombe en panne, enfin les octets sont délivrés dans l'ordre où ils ont été émis. Ces contrôles et cette sécurité ont un prix : TCP a un overhead élevé.
t t t
There’s a second protocol, called User Datagram Protocol (UDP), which doesn’t guarantee that the packets will be delivered and doesn’t guarantee that they will arrive in the order they were sent. It’s called an “unreliable protocol” (TCP is a “reliable protocol”), which sounds bad, but because it’s much faster it can be useful. There are some applications, such as an audio signal, in which it isn’t so critical if a few packets are dropped here or there but speed is vital. Or consider a time-of-day server, where it really doesn’t matter if one of the messages is lost. Also, some applications might be able to fire off a UDP message to a server and can then assume, if there is no response in a reasonable period of time, that the message was lost. t Il existe un deuxième protocole, appelé User Datagram Protocol (UDP), qui ne garantit pas que les paquets seront acheminés ni qu'ils arriveront dans l'ordre d'émission. On l'appelle protocole peu sûr « (TCP est un protocole ]sûr), ce qui n'est pas très vendeur, mais il peut être très utile car il est beaucoup plus rapide. Il existe des applications, comme la transmission d'un signal audio, pour lesquelles il n'est pas critique de perdre quelques paquets çà et là mais où en revanche la vitesse est vitale. Autre exemple, considérons un serveur de date et heure, pour lequel on n'a pas vraiment à se préoccuper de savoir si un message a été perdu. De plus, certaines applications sont en mesure d'envoyer à un serveur un message UDP et ensuite d'estimer que le message a été perdu si elles n'ont pas de réponse dans un délai raisonnable.
t t t
Typically, you’ll do most of your direct network programming with TCP, and only occasionally will you use UDP. There’s a more complete treatment of UDP, including an example, in the first edition of this book (available on the CD ROM bound into this book, or as a free download from www.BruceEckel.com). t En règle générale, la majorité de la programmation réseau directe est réalisée avec TCP, et seulement occasionnellement avec UDP. Vous trouverez un traitement plus complet sur UDP, avec un exemple, dans la première édition de ce livre (disponible sur le CD ROM fourni avec ce llvre, ou en téléchargement libre depuis www.BruceEckel.com).
t t t

Using URLs from within an applet

t

Utiliser des URLs depuis un applet

t t t
It’s possible for an applet to cause the display of any URL through the Web browser the applet is running within. You can do this with the following line: t Un applet a la possibilité d'afficher n'importe quelle URL au moyen du navigateur sur lequel il tourne. Ceci est réalisé avec la ligne suivante :
t t t
getAppletContext().showDocument(u);
t
getAppletContext().showDocument(u);
t t t
in
which u is the URL object. Here’s a simple example that
redirects you to another Web page. Although you’re just redirected to an
HTML page, you could also redirect to the output of a CGI program.


t dans laquelle u est l'objet URL. Voici un exemple simple qui nous redirige vers une autre page Web. Bien que nous soyons seulement redirigés vers une page HTML, nous pourrions l'être de la même manière vers la sortie d'un programme CGI.
t t t
//: c15:ShowHTML.java
// <applet code=ShowHTML width=100 height=50>
// </applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import com.bruceeckel.swing.*;

public class ShowHTML extends JApplet {
  JButton send = new JButton("Go");
  JLabel l = new JLabel();
  public void init() {
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    send.addActionListener(new Al());
    cp.add(send);
    cp.add(l);
  }
  class Al implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
      try {
        // This could be a CGI program instead of
        // an HTML page.
        URL u = new URL(getDocumentBase(),
          "FetcherFrame.html");
        // Display the output of the URL using
        // the Web browser, as an ordinary page:
        getAppletContext().showDocument(u);
      } catch(Exception e) {
        l.setText(e.toString());
      }
    }
  }
  public static void main(String[] args) {
    Console.run(new ShowHTML(), 100, 50);
  }
} ///:~
t
//: c15:ShowHTML.java
// <applet code=ShowHTML width=100 height=50>
// </applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import com.bruceeckel.swing.*;

public class ShowHTML extends JApplet {
  JButton send = new JButton("Go");
  JLabel l = new JLabel();
  public void init() {
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    send.addActionListener(new Al());
    cp.add(send);
    cp.add(l);
  }
  class Al implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
      try {
        // Ceci pourrait être un programme CGI
        // au lieu d'une page HTML.
        URL u = new URL(getDocumentBase(),
          "FetcherFrame.html");
        // Afficher la sortie de l'URL en utilisant
        // le navigateur Web, comme une page ordinaire:
        getAppletContext().showDocument(u);
      } catch(Exception e) {
        l.setText(e.toString());
      }
    }
  }
  public static void main(String[ « args) {
    Console.run(new ShowHTML(), 100, 50);
  }
} ///:~
t t t
The beauty of the URL class is how much it shields you from. You can connect to Web servers without knowing much at all about what’s going on under the covers. t Il est beau de voir combien la classe URL nous évite la complexité. Il est possible de se connecter à un serveur Web sans avoir à connaître ce qui se passe à bas niveau.
t t t

Reading a file from the server

t

Lire un fichier depuis un serveur

t t t
A variation on the above program reads a file located on the server. In this case, the file is specified by the client: t Une variante du programme ci-dessus consiste à lire un fichier situé sur le serveur. Dans ce cas, le fichier est décrit par le client :
t t t
//: c15:Fetcher.java
// <applet code=Fetcher width=500 height=300>
// </applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import com.bruceeckel.swing.*;

public class Fetcher extends JApplet {
  JButton fetchIt= new JButton("Fetch the Data");
  JTextField f =
    new JTextField("Fetcher.java", 20);
  JTextArea t = new JTextArea(10,40);
  public void init() {
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    fetchIt.addActionListener(new FetchL());
    cp.add(new JScrollPane(t));
    cp.add(f); cp.add(fetchIt);
  }
  public class FetchL implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      try {
        URL url = new URL(getDocumentBase(),
          f.getText());
        t.setText(url + "\n");
        InputStream is = url.openStream();
        BufferedReader in = new BufferedReader(
          new InputStreamReader(is));
        String line;
        while ((line = in.readLine()) != null)
          t.append(line + "\n");
      } catch(Exception ex) {
        t.append(ex.toString());
      }
    }
  }
  public static void main(String[] args) {
    Console.run(new Fetcher(), 500, 300);
  }
} ///:~
t
//: c15:Fetcher.java
// <applet code=Fetcher width=500 height=300>
// </applet>
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import com.bruceeckel.swing.*;

public class Fetcher extends JApplet {
  JButton fetchIt= new JButton("Fetch the Data");
  JTextField f =
    new JTextField("Fetcher.java", 20);
  JTextArea t = new JTextArea(10,40);
  public void init() {
    Container cp = getContentPane();
    cp.setLayout(new FlowLayout());
    fetchIt.addActionListener(new FetchL());
    cp.add(new JScrollPane(t));
    cp.add(f); cp.add(fetchIt);
  }
  public class FetchL implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      try {
        URL url = new URL(getDocumentBase(),
          f.getText());
        t.setText(url + "\n");
        InputStream is = url.openStream();
        BufferedReader in = new BufferedReader(
          new InputStreamReader(is));
        String line;
        while ((line = in.readLine()) != null)
          t.append(line + "\n");
      } catch(Exception ex) {
        t.append(ex.toString());
      }
    }
  }
  public static void main(String[ « args) {
    Console.run(new Fetcher(), 500, 300);
  }
} ///:~
t t t
The creation of the URL object is similar to the previous example—getDocumentBase( ) is the starting point as before, but this time the name of the file is read from the JTextField. Once the URL object is created, its String version is placed in the JTextArea so we can see what it looks like. Then an InputStream is procured from the URL, which in this case will simply produce a stream of the characters in the file. After converting to a Reader and buffering, each line is read and appended to the JTextArea. Note that the JTextArea has been placed inside a JScrollPane so that scrolling is handled automatically. t La création de l'objet URL est semblable à celle de l'exemple précédent. Comme d'habitude, getDocumentBase( ) est le point de départ, mais cette fois le nom de fichier est lu depuis le JTextField. Un fois l'objet URL créé, sa version String est affichée dans le JTextArea afin que nous puissions la visualiser. Puis un InputStream est créé à partir de l'URL, qui dans ce cas va simplement créer un flux de caractères vers le fichier. Après avoir été convertie vers un Reader et bufferisée, chaque ligne est lue et ajoutée au JTextArea. Notons que le JTextArea est placé dans un JScrollPane afin que le scrolling soit pris en compte automatiquement.
t t t

More to networking

t

En savoir plus sur le travail en réseau

t t t
There’s actually a lot more to networking than can be covered in this introductory treatment. Java networking also provides fairly extensive support for URLs, including protocol handlers for different types of content that can be discovered at an Internet site. You can find other Java networking features fully and carefully described in Java Network Programming by Elliotte Rusty Harold (O’Reilly, 1997). t En réalité, bien d'autres choses à propos du travail en réseau pourraient être traitées dans cette introduction. Le travail en réseau Java fournit également un support correct et étendu pour les URLs, incluant des handlers de protocole pour les différents types de contenu que l'on peut trouver sur un site Internet. Vous découvrirez d'autres fonctionnalités réseau de Java, complètement et minutieusement décrites dans Java Network Programming de Elliotte Rusty Harold (O.Reilly, 1997).
t t t

Java Database Connectivity (JDBC)

t

Se connecter aux bases de données : Java Database Connectivity (JDBC)

t t t
It has been estimated that half of all software development involves client/server operations. A great promise of Java has been the ability to build platform-independent client/server database applications. This has come to fruition with Java DataBase Connectivity (JDBC). t On a pu estimer que la moitié du développement de programmes implique des opérations client/serveur. Une des grandes promesses tenues par Java fut sa capacité à construire des applications de base de données client/serveur indépendantes de la plate-forme. C'est ce qui est réalisé avec Java DataBase Connectivity (JDBC).
t t t
One of the major problems with databases has been the feature wars between the database companies. There is a “standard” database language, Structured Query Language (SQL-92), but you must usually know which database vendor you’re working with despite the standard. JDBC is designed to be platform-independent, so you don’t need to worry about the database you’re using while you’re programming. However, it’s still possible to make vendor-specific calls from JDBC so you aren’t restricted from doing what you must. t Un des problèmes majeurs rencontrés avec les bases de données fut la guerre des fonctionnalités entre les compagnies fournissant ces bases de données. Il existe un langage standard de base de données, Structured Query Language (SQL-92), mais il est généralement préférable de connaître le vendeur de la base de données avec laquelle on travaille, malgré ce standard. JDBC est conçu pour être indépendant de la plate-forme, ainsi lorsqu'on programme on n'a pas à se soucier de la base de données qu'on utilise. Il est toutefois possible d'effectuer à partir de JDBC des appels spécifiques vers une base particulière afin de ne pas être limité dans ce que l'on pourrait faire.
t t t
One place where programmers may need to use SQL type names is in the SQL TABLE CREATE statement when they are creating a new database table and defining the SQL type for each column. Unfortunately there are significant variations between SQL types supported by different database products. Different databases that support SQL types with the same semantics and structure may give those types different names. Most major databases support an SQL data type for large binary values: in Oracle this type is called a LONG RAW, Sybase calls it IMAGE, Informix calls it BYTE, and DB2 calls it LONG VARCHAR FOR BIT DATA. Therefore, if database portability is a goal you should try to use only generic SQL type identifiers. t Il existe un endroit pour lequel les programmeurs auraient besoin d'utiliser les noms de type SQL, c'est dans l'instruction SQL TABLE CREATE lorsqu'on crée une nouvelle table de base de données et qu'on définit le type SQL de chaque colonne. Malheureusement il existe des variantes significatives entre les types SQL supportés par différents produits base de données. Des bases de données différentes supportant des types SQL de même sémantique et de même structure peuvent appeler ces types de manières différentes. La plupart des bases de données importantes supportent un type de données SQL pour les grandes valeurs binaires : dans Oracle ce type s'appelle LONG RAW, Sybase le nomme IMAGE, Informix BYTE, et DB2 LONG VARCHAR FOR BIT DATA. Par conséquent, si on a pour but la portabilité des bases de données il faut essayer de n'utiliser que les identifiants de type SQL génériques.
t t t
Portability is an issue when writing for a book where readers may be testing the examples with all kinds of unknown data stores. I have tried to write these examples to be as portable as possible. You should also notice that the database-specific code has been isolated in order to centralize any changes that you may need to perform to get the examples operational in your environment. t La portabilité est une question d'actualité lorsqu'on écrit pour un livre dont les lecteurs vont tester les exemples avec toute sorte de stockage de données inconnus. J'ai essayé de rendre ces exemples aussi portables qu'il était possible. Remarquez également que le code spécifique à la base de données a été isolé afin de centraliser toutes les modifications que vous seriez obligés d'effectuer pour que ces exemples deviennent opérationnels dans votre environnement.
t t t
JDBC, like many of the APIs in Java, is designed for simplicity. The method calls you make correspond to the logical operations you’d think of doing when gathering data from a database: connect to the database, create a statement and execute the query, and look at the result set. t JDBC, comme bien des APIs Java, est conçu pour être simple. Les appels de méthode que l'on utilise correspondent aux opérations logiques auxquelles on pense pour obtenir des données depuis une base de données, créer une instruction, exécuter la demande, et voir le résultat.
t t t
To allow this platform independence, JDBC provides a driver manager that dynamically maintains all the driver objects that your database queries will need. So if you have three different kinds of vendor databases to connect to, you’ll need three different driver objects. The driver objects register themselves with the driver manager at the time of loading, and you can force the loading using Class.forName( ). t Pour permettre cette indépendance de plate-forme, JDBC fournit un gestionnaire de driver qui maintient dynamiquement les objets driver nécessités par les interrogations de la base. Ainsi si on doit se connecter à trois différentes sortes de base, on a besoin de trois objets driver différents. Les objets driver s'enregistrent eux-même auprès du driver manager lors de leur chargement, et on peut forcer le chargement avac la méthode Class.forName( ).
t t t
To open a database, you must create a “database URL” that specifies: t Pour ouvrir une base de données, il faut créer une « URL ]de base de données » qui spécifie :
t t t
  1. That you’re using JDBC with “jdbc.”
  2. The “subprotocol”: the name of the driver or the name of a database connectivity mechanism. Since the design of JDBC was inspired by ODBC, the first subprotocol available is the “jdbc-odbc bridge,” specified by “odbc.”
  3. The database identifier. This varies with the database driver used, but it generally provides a logical name that is mapped by the database administration software to a physical directory where the database tables are located. For your database identifier to have any meaning, you must register the name using your database administration software. (The process of registration varies from platform to platform.)
t
  1. Qu'on utilise JDBC avec « jdbc ».]
  2. Le « sous-protocole » : le nom du driver ou le nom du mécanisme de connectivité à la base de données. Parce que JDBC a été inspiré par ODBC, le premier sous-protocole disponible est la « passerelle » jdbc-odbc », « spécifiée par « odbc ».]
  3. L'identifiant de la base de données. Il varie avec le driver de base de donnée utilisé, mais il existe généralement un nom logique qui est associé par le software d'administration de la base à un répertoire physique où se trouvent les tables de la base de données. Pour qu'un identifiant de base de données ait une signification, il faut l'enregistrer en utilisant le software d'administration de la base (cette opération varie d'une plate-forme à l'autre).
t t t
All this information is combined into one string, the “database URL.” For example, to connect through the ODBC subprotocol to a database identified as “people,” the database URL could be: t Toute cette information est condensée dans une chaîne de caractères, l'URL de la base de données.]Par exemple, pour se connecter au moyen du protocole ODBC à une base appelée » people, « l'URL de base de données doit être :
t t t
String dbUrl = "jdbc:odbc:people";
t
String dbUrl = "jdbc:odbc:people";
t t t
If you’re connecting across a
network, the database URL will contain the connection information identifying
the remote machine and can become a bit intimidating. Here is an example of a
CloudScape database being called from a remote client utilizing
RMI:

t Si on se connecte à travers un réseau, l'URL de base de données doit contenir l'information de connexion identifiant la machine distante, et peut alors devenir intimidante. Voici en exemple la base de données CloudScape que l'on appelle depuis un client éloigné en utilisant RMI :
t t t
jdbc:rmi://192.168.170.27:1099/jdbc:cloudscape:db
t
jdbc:rmi://192.168.170.27:1099/jdbc:cloudscape:db
t t t
This database URL is really two jdbc
calls in one. The first part
“jdbc:rmi://192.168.170.27:1099/”
uses RMI to make the connection to the remote database engine listening on port
1099 at IP Address 192.168.170.27. The second part of the URL,
“jdbc:cloudscape:db”
conveys the more typical settings using the subprotocol and database name but
this will only happen after the first section has made the connection via RMI to
the remote machine.
t En réalité cette URL de base de données comporte deux appels jdbc en un. La première partie jdbc:rmi://192.168.170.27:1099/ « utilise RMI pour effectuer une connexion sur le moteur distant de base de données à l'écoute sur le port 1099 de l'adresse IP 192.168.170.27. La deuxième partie de l'URL, [jdbc:cloudscape:db] représente une forme plus connue utilisant le sous-protocole et le nom de la base, mais elle n'entrera en jeu que lorsque la première section aura établi la connexion à la machine distante via RMI.
t t t
When you’re ready to connect to the
database, call the static method
DriverManager.getConnection( ) and pass it the database URL, the
user name, and a password to get into the database. You get back a
Connection object that you can then use to query and manipulate the
database.
t Lorsqu'on est prêt à se connecter à une base, on appelle la méthode statique DriverManager.getConnection( ) en lui fournissant l'URL de base de données, le nom d'utilisateur et le mot de passe pour accéder à la base. On reçoit en retour un objet Connection que l'on peut ensuite utiliser pour effectuer des demandes et manipuler la base de données.
t t t
The following example opens a database of
contact information and looks for a person’s last name as given on the
command line. It selects only the names of people that have email addresses,
then prints out all the ones that match the given last name:

t L'exemple suivant ouvre une base d'« information de contact » et cherche le nom de famille d'une personne, donné sur la ligne de commande. Il sélectionne d'abord les noms des personnes qui ont une adresse email, puis imprime celles qui correspondent au nom donné :
t t t
//: c15:jdbc:Lookup.java
// Looks up email addresses in a
// local database using JDBC.
import java.sql.*;

public class Lookup {
  public static void main(String[] args)
  throws SQLException, ClassNotFoundException {
    String dbUrl = "jdbc:odbc:people";
    String user = "";
    String password = "";
    // Load the driver (registers itself)
    Class.forName(
      "sun.jdbc.odbc.JdbcOdbcDriver");
    Connection c = DriverManager.getConnection(
      dbUrl, user, password);
    Statement s = c.createStatement();
    // SQL code:
    ResultSet r =
      s.executeQuery(
        "SELECT FIRST, LAST, EMAIL " +
        "FROM people.csv people " +
        "WHERE " +
        "(LAST='" + args[0] + "') " +
        " AND (EMAIL Is Not Null) " +
        "ORDER BY FIRST");
    while(r.next()) {
      // Capitalization doesn't matter:
      System.out.println(
        r.getString("Last") + ", "
        + r.getString("fIRST")
        + ": " + r.getString("EMAIL") );
    }
    s.close(); // Also closes ResultSet
  }
} ///:~
t
//: c15:jdbc:Lookup.java
// Cherche les adresses email dans une  
// base de données locale en utilisant JDBC.
import java.sql.*;

public class Lookup {
  public static void main(String[ « args)
  throws SQLException, ClassNotFoundException {
    String dbUrl = "jdbc:odbc:people";
    String user = "";
    String password = "";
    // Charger le driver (qui s'enregistrera lui-même)
    Class.forName(
      "sun.jdbc.odbc.JdbcOdbcDriver");
    Connection c = DriverManager.getConnection(
      dbUrl, user, password);
    Statement s = c.createStatement();
    // code SQL:
    ResultSet r =
      s.executeQuery(
        "SELECT FIRST, LAST, EMAIL " +
        "FROM people.csv people " +
        "WHERE " +
        "(LAST='" + args[0 « + "') " +
        " AND (EMAIL Is Not Null) " +
        "ORDER BY FIRST");
    while(r.next()) {
      // minuscules et majuscules n'ont
      // aucune importance:
      System.out.println(
        r.getString("Last") + ", "
        + r.getString("fIRST")
        + ": " + r.getString("EMAIL") );
    }
    s.close(); // fermer également ResultSet
  }
} ///:~
t t t
You can see the creation of the database URL as previously described. In this example, there is no password protection on the database so the user name and password are empty strings. t Une URL de base de données est créée comme précédemment expliqué. Dans cet exemple, il n'y a pas de protection par mot de passe, c'est pourquoi le nom d'utilisateur et le mot de passe sont des chaînes vides.
t t t
Once the connection is made with DriverManager.getConnection( ), you can use the resulting Connection object to create a Statement object using the createStatement( ) method. With the resulting Statement, you can call executeQuery( ), passing in a string containing an SQL-92 standard SQL statement. (You’ll see shortly how you can generate this statement automatically, so you don’t have to know much about SQL.) t Une fois la connexion établie avec DriverManager.getConnection( ) l'objet résultant Connection sert à créer un objet Statement au moyen de la méthode createStatement( ). Avec cet objet Statement, on peut appeler executeQuery( ) en lui passant une chaîne contenant une instruction standard SQL-92 (il n'est pas difficile de voir comment générer cette instruction automatiquement, on n'a donc pas à connaître grand'chose de SQL).
t t t
The executeQuery( ) method returns a ResultSet object, which is an iterator: the next( ) method moves the iterator to the next record in the statement, or returns false if the end of the result set has been reached. You’ll always get a ResultSet object back from executeQuery( ) even if a query results in an empty set (that is, an exception is not thrown). Note that you must call next( ) once before trying to read any record data. If the result set is empty, this first call to next( ) will return false. For each record in the result set, you can select the fields using (among other approaches) the field name as a string. Also note that the capitalization of the field name is ignored—it doesn’t matter with an SQL database. You determine the type you’ll get back by calling getInt( ), getString( ), getFloat( ), etc. At this point, you’ve got your database data in Java native format and can do whatever you want with it using ordinary Java code. t La méthode executeQuery( ) renvoie un objet ResultSet, qui est un itérateur : la méthode next( ) fait pointer l'objet itérateur sur l'enregistrement suivant dans l'instruction, ou bien renvoie la valeur false si la fin de l'ensemble résultat est atteinte. On obtient toujours un objet ResultSet en réponse à la méthode executeQuery( ) même lorsqu'une demande débouche sur un ensemble vide (autrement dit aucune exception n'est générée). Notons qu'il faut appeler la méthode next( ) au moins une fois avant de tenter de lire un enregistrement de données. Si l'ensemble résultant est vide, ce premier appel de next( ) renverra la valeur false. Pour chaque enregistrement dans l'ensemble résultant, on peut sélectionner les champs en utilisant (entre autres solutions) une chaîne représentant leur nom. Remarquons aussi que la casse du nom de champ est ignorée dans les transactions avec une base de donnée. Le type de données que l'on veut récupérer est déterminé par le nom de la méthode appelée : getInt( ), getString( ), getFloat( ), etc. Á ce moment, on dispose des données de la base en format Java natif et on peut les traiter comme bon nous semble au moyen du code Java habituel.
t t t

Getting the example to work

t

Faire fonctionner l'exemple

t t t
With JDBC, understanding the code is relatively simple. The confusing part is making it work on your particular system. The reason this is confusing is that it requires you to figure out how to get your JDBC driver to load properly, and how to set up a database using your database administration software. t Avec JDBC, il est relativement simple de comprendre le code. Le côté difficile est de faire en sorte qu'il fonctionne sur votre système particulier. La raison de cette difficulté est que vous devez savoir comment charger proprement le driver JDBC, et comment initialiser une base de données en utilisant le software d'administration de la base.
t t t
Of course, this process can vary radically from machine to machine, but the process I used to make it work under 32-bit Windows might give you clues to help you attack your own situation. t Bien entendu, ce travail peut varier de façon radicale d'une machine à l'autre, mais la manière dont j'ai procédé pour le faire fonctionner sur un système Windows 32 bits vous donnera sans doute des indications qui vous aideront à attaquer votre propre situation.
t t t

Step 1: Find the JDBC Driver

t

Étape 1 : Trouver le Driver JDBC

t t t
The program above contains the statement: t Le programme ci-dessus contient l'instruction :
t t t
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
t
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
t t t
This implies a directory structure, which
is deceiving. With this particular installation of JDK 1.1, there was no file
called JdbcOdbcDriver.class, so if you looked at this example and went
searching for it you’d be frustrated. Other published examples use a
pseudo name, such as “myDriver.ClassName,” which is less than
helpful. In fact, the load statement above for the jdbc-odbc driver (the only
one that actually comes with the JDK) appears in only a few places in the online
documentation (in particular, a page labeled “JDBC-ODBC Bridge
Driver”). If the load statement above doesn’t work, then the name
might have been changed as part of a Java version change, so you should hunt
through the documentation again.

t Ceci suggère une structure de répertoire, ce qui est trompeur. Avec cette installation particulière du JDK 1.1, il n'existe pas de fichier nommé JdbcOdbcDriver.class, et si vous avez cherché ce fichier après avoir regardé l'exemple vous avez dû être déçus. D'autre exemples publiés utilisent un pseudo nom, comme myDriver.ClassName, « ce qui nous aide encore moins. En fait, l'instruction de chargement du driver jdbc-odbc (le seul existant actuellement dans le JDK) apparaît en peu d'endroits dans la documentation en ligne (en particulier, une page appelée JDBC-ODBC Bridge Driver]). Si l'instruction de chargement ci-dessus ne fonctionne pas, il est possible que le nom ait été changé à l'occasion d'une évolution de version Java, et vous devez repartir en chasse dans la documention.
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel