 |
 |
15) Informatique distribuée |
|
 |
|
Texte original |
 |
Traducteur :
Jean-Pierre Vidal, Alban Peignier |
|
 |
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
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.
|
 |
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( ).
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
Datagrams
|
 |
Les Datagrammes
|
 |
 |
 |
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.
|
 |
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é.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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).
|
 |
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).
|
 |
 |
 |
Using URLs from within an
applet
|
 |
Utiliser des URLs depuis un applet
|
 |
 |
 |
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:
|
 |
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 :
|
 |
 |
 |
getAppletContext().showDocument(u);
|
 |
getAppletContext().showDocument(u);
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
//: 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);
}
} ///:~
|
 |
//: 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); } } ///:~
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
Reading a file from the server
|
 |
Lire un fichier depuis un serveur
|
 |
 |
 |
A variation on the above program reads a
file located on the server. In this case, the file is specified by the
client:
|
 |
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 :
|
 |
 |
 |
//: 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);
}
} ///:~
|
 |
//: 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); } } ///:~
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
More to networking
|
 |
En savoir plus sur le travail en réseau
|
 |
 |
 |
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).
|
 |
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).
|
 |
 |
 |
Java Database Connectivity (JDBC)
|
 |
Se connecter aux bases de données : Java Database Connectivity
(JDBC)
|
 |
 |
 |
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).
|
 |
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).
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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( ).
|
 |
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( ).
|
 |
 |
 |
To open a database, you must create a
“database URL” that
specifies:
|
 |
Pour ouvrir une base de données, il faut créer une « URL ]de base de
données » qui spécifie :
|
 |
 |
 |
- That you’re using
JDBC with
“jdbc.”
- 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.”
- 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.)
|
 |
- Qu'on utilise JDBC avec « jdbc ».]
- 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 ».]
- 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).
|
 |
 |
 |
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:
|
 |
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 :
|
 |
 |
 |
String dbUrl = "jdbc:odbc:people";
|
 |
String dbUrl = "jdbc:odbc:people";
|
 |
 |
 |
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:
|
 |
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 :
|
 |
 |
 |
jdbc:rmi://192.168.170.27:1099/jdbc:cloudscape:db
|
 |
jdbc:rmi://192.168.170.27:1099/jdbc:cloudscape:db
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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:
|
 |
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é :
|
 |
 |
 |
//: 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
}
} ///:~
|
 |
//: 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 } } ///:~
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.)
|
 |
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).
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
Getting the example to work
|
 |
Faire fonctionner l'exemple
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
Step 1: Find the JDBC Driver
|
 |
Étape 1 : Trouver le Driver JDBC
|
 |
 |
 |
The program above contains the
statement:
|
 |
Le programme ci-dessus contient l'instruction :
|
 |
 |
 |
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
|
 |
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
|
 |
 |
 |
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.
|
 |
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.
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |