Add mention of transactions and large objects.

Still need the code updated for LO examples.
This commit is contained in:
Thomas G. Lockhart 1999-10-04 15:16:35 +00:00
parent 0655b1500f
commit ee8d39a852
1 changed files with 449 additions and 404 deletions

View File

@ -1,384 +1,385 @@
<Chapter Id="jdbc"> <chapter id="jdbc">
<Title>JDBC Interface</Title> <title>JDBC Interface</title>
<para> <para>
<note> <note>
<title>Author</title> <title>Author</title>
<para> <para>
Written by <ulink url="peter@retep.org.uk">Peter T. Mount</ulink>, the Written by <ulink url="peter@retep.org.uk">Peter T. Mount</ulink>, the
author of the <acronym>JDBC</acronym> driver. author of the <acronym>JDBC</acronym> driver.
</para> </para>
</note> </note>
</para> </para>
<para> <para>
<acronym>JDBC</acronym> is a core <acronym>API</acronym> of Java 1.1 and later. <acronym>JDBC</acronym> is a core <acronym>API</acronym> of Java 1.1 and later.
It provides a standard set of It provides a standard set of
interfaces to <acronym>SQL</acronym>-compliant databases. interfaces to <acronym>SQL</acronym>-compliant databases.
</para> </para>
<para>
<application>Postgres</application> provides
a type 4 <acronym>JDBC</acronym> Driver. Type 4 indicates that the driver
is written in Pure Java, and communicates in the database's own network
protocol. Because of this, the driver is platform independent. Once compiled,
the driver can be used on any platform.
</para>
<sect1> <para>
<title>Building the <acronym>JDBC</acronym> Interface</title> <application>Postgres</application> provides
a <firstterm>type 4</firstterm> <acronym>JDBC</acronym> Driver.
Type 4 indicates that the driver
is written in Pure Java, and communicates in the database's own network
protocol. Because of this, the driver is platform independent. Once compiled,
the driver can be used on any platform.
</para>
<sect2> <sect1>
<title>Compiling the Driver</title> <title>Building the <acronym>JDBC</acronym> Interface</title>
<para> <sect2>
The driver's source is located in the <filename>src/interfaces/jdbc</filename> <title>Compiling the Driver</title>
directory of the
source tree. To compile simply change directory to that directory, and type:
<programlisting> <para>
The driver's source is located in the <filename>src/interfaces/jdbc</filename>
directory of the
source tree. To compile simply change directory to that directory, and type:
<programlisting>
% make % make
</programlisting> </programlisting>
</para> </para>
<para> <para>
Upon completion, you will find the archive <filename>postgresql.jar</filename> Upon completion, you will find the archive <filename>postgresql.jar</filename>
in the current in the current
directory. This is the <acronym>JDBC</acronym> driver. directory. This is the <acronym>JDBC</acronym> driver.
<note> <note>
<para> <para>
You must use <application>make</application>, You must use <application>make</application>,
not <application>javac</application>, not <application>javac</application>,
as the driver uses some dynamic as the driver uses some dynamic
loading techniques for performance reasons, loading techniques for performance reasons,
and <application>javac</application> cannot cope. and <application>javac</application> cannot cope.
The <filename>Makefile</filename> will generate the jar archive. The <filename>Makefile</filename> will generate the jar archive.
</para> </para>
</note> </note>
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Installing the Driver</title> <title>Installing the Driver</title>
<para> <para>
To use the driver, the jar archive postgresql.jar needs to be included in To use the driver, the jar archive postgresql.jar needs to be included in
the CLASSPATH. the <envar>CLASSPATH</envar>.
</para> </para>
<para>
Example:
</para>
<para>
I have an application that uses the <acronym>JDBC</acronym> driver to access a large database
containing astronomical objects. I have the application and the jdbc driver
installed in the /usr/local/lib directory, and the java jdk installed in /usr/local/jdk1.1.6.
</para>
<para> <sect3>
To run the application, I would use: <title>Example</title>
</para>
<para> <para>
export CLASSPATH = \ I have an application that uses the <acronym>JDBC</acronym> driver to access a large database
/usr/local/lib/finder.jar:/usr/local/lib/postgresql.jar:. containing astronomical objects. I have the application and the jdbc driver
installed in the /usr/local/lib directory, and the java jdk installed in /usr/local/jdk1.1.6.
</para>
<para>
To run the application, I would use:
<programlisting>
export CLASSPATH = /usr/local/lib/finder.jar:/usr/local/lib/postgresql.jar:.
java uk.org.retep.finder.Main java uk.org.retep.finder.Main
</para> </programlisting>
<para> </para>
Loading the driver is covered later on in this chapter.
</para>
</sect2>
</sect1>
<sect1> <para>
<title>Preparing the Database for <acronym>JDBC</acronym></title> Loading the driver is covered later on in this chapter.
</para>
</sect3>
</sect2>
</sect1>
<para> <sect1>
Because Java can only use TCP/IP connections, the <application>Postgres</application> postmaster <title>Preparing the Database for <acronym>JDBC</acronym></title>
must be running with the -i flag.
</para> <para>
<para> Because Java can only use TCP/IP connections, the <application>Postgres</application> postmaster
Also, the <filename>pg_hba.conf</filename> file must be configured. It's located in the PGDATA must be running with the -i flag.
directory. In a default installation, this file permits access only by UNIX </para>
domain sockets. For the <acronym>JDBC</acronym> driver to connect to the same localhost, you need
to add something like: <para>
</para> Also, the <filename>pg_hba.conf</filename> file must be configured. It's located in the PGDATA
<para> directory. In a default installation, this file permits access only by Unix
domain sockets. For the <acronym>JDBC</acronym> driver to connect to the same localhost, you need
to add something like:
<programlisting>
host all 127.0.0.1 255.255.255.255 password host all 127.0.0.1 255.255.255.255 password
</para> </programlisting>
<para>
Here access to all databases are possible from the local machine
with <acronym>JDBC</acronym>.
</para>
<para> Here access to all databases are possible from the local machine
The <acronym>JDBC</acronym> Driver supports trust, ident, with <acronym>JDBC</acronym>.
password and crypt authentication methods. </para>
</para>
</sect1>
<sect1> <para>
<title>Using the Driver</title> The <acronym>JDBC</acronym> Driver supports trust, ident,
password and crypt authentication methods.
</para>
</sect1>
<para> <sect1>
This section is not intended as a complete guide to <title>Using the Driver</title>
<acronym>JDBC</acronym> programming, but
should help to get you started. For more information refer to the standard
<acronym>JDBC</acronym> <acronym>API</acronym> documentation.
</para>
<para>
Also, take a look at the examples included with the source. The basic
example is used here.
</para>
</sect1>
<sect1> <para>
<title>Importing <acronym>JDBC</acronym></title> This section is not intended as a complete guide to
<acronym>JDBC</acronym> programming, but
should help to get you started. For more information refer to the standard
<acronym>JDBC</acronym> <acronym>API</acronym> documentation.
Also, take a look at the examples included with the source. The basic
example is used here.
</para>
</sect1>
<para> <sect1>
Any source that uses <acronym>JDBC</acronym> <title>Importing <acronym>JDBC</acronym></title>
needs to import the java.sql package, using:
<programlisting> <para>
Any source that uses <acronym>JDBC</acronym>
needs to import the java.sql package, using:
<programlisting>
import java.sql.*; import java.sql.*;
</programlisting> </programlisting>
<important> <important>
<para> <para>
Do not import the postgresql package. If you do, your source will not Do not import the postgresql package. If you do, your source will not
compile, as javac will get confused. compile, as javac will get confused.
</para> </para>
</important> </important>
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
<title>Loading the Driver</title> <title>Loading the Driver</title>
<para> <para>
Before you can connect to a database, you need to load the driver. There Before you can connect to a database, you need to load the driver. There
are two methods available, and it depends on your code to the best one to use. are two methods available, and it depends on your code to the best one to use.
</para> </para>
<para> <para>
In the first method, your code implicitly loads the driver using the In the first method, your code implicitly loads the driver using the
Class.forName() method. For <application>Postgres</application>, you would use: <function>Class.forName()</function> method.
For <application>Postgres</application>, you would use:
<programlisting> <programlisting>
Class.forName("postgresql.Driver"); Class.forName("postgresql.Driver");
</programlisting> </programlisting>
This will load the driver, and while loading, the driver will automatically This will load the driver, and while loading, the driver will automatically
register itself with <acronym>JDBC</acronym>. register itself with <acronym>JDBC</acronym>.
</para> </para>
<para> <para>
Note: The <function>forName()</function> method Note: The <function>forName()</function> method
can throw a ClassNotFoundException, so you will can throw a <literal>ClassNotFoundException</literal>, so you will
need to catch it if the driver is not available. need to catch it if the driver is not available.
</para> </para>
<para> <para>
This is the most common method to use, but restricts your code to use just This is the most common method to use, but restricts your code to use just
<application>Postgres</application>. <application>Postgres</application>.
If your code may access another database in the future, and you If your code may access another database in the future, and you
don't use our extensions, then the second method is advisable. don't use our extensions, then the second method is advisable.
</para> </para>
<para> <para>
The second method passes the driver as a parameter to the JVM as it starts, The second method passes the driver as a parameter to the JVM as it starts,
using the -D argument. using the -D argument. Example:
</para>
<para>
Example:
<programlisting> <programlisting>
% java -Djdbc.drivers=postgresql.Driver example.ImageViewer % java -Djdbc.drivers=postgresql.Driver example.ImageViewer
</programlisting> </programlisting>
</para>
<para> In this example, the JVM will attempt to load the driver as part of it's
In this example, the JVM will attempt to load the driver as part of it's initialisation. Once done, the ImageViewer is started.
initialisation. Once done, the ImageViewer is started. </para>
</para> <para>
<para> Now, this method is the better one to use because it allows your code to
Now, this method is the better one to use because it allows your code to be used with other databases, without recompiling the code. The only thing
be used with other databases, without recompiling the code. The only thing that would also change is the URL, which is covered next.
that would also change is the URL, which is covered next. </para>
</para>
<para> <para>
One last thing. When your code then tries to open a Connection, and you get One last thing. When your code then tries to open a Connection, and you get
a <literal>No driver available</literal> SQLException being thrown, a <literal>No driver available</literal> SQLException being thrown,
this is probably this is probably
caused by the driver not being in the classpath, or the value in the parameter caused by the driver not being in the classpath, or the value in the parameter
not being correct. not being correct.
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
<title>Connecting to the Database</title> <title>Connecting to the Database</title>
<para> <para>
With <acronym>JDBC</acronym>, a database is represented by a URL With <acronym>JDBC</acronym>, a database is represented by a URL
(Uniform Resource Locator). (Uniform Resource Locator).
With <application>Postgres</application>, this takes one of the following With <application>Postgres</application>, this takes one of the following
forms: forms:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
jdbc:postgresql:<replaceable class="parameter">database</replaceable> jdbc:postgresql:<replaceable class="parameter">database</replaceable>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
jdbc:postgresql://<replaceable class="parameter">host</replaceable>/<replaceable class="parameter">database</replaceable> jdbc:postgresql://<replaceable class="parameter">>hos</replaceable>>/<replaceable class="parameter">database</replaceable>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
jdbc:postgresql://<replaceable class="parameter">host</replaceable>:<replaceable class="parameter">port</replaceable>/<replaceable class="parameter">database</replaceable> jdbc:postgresql://<replaceable class="parameter">>hos</replaceable>><replaceable class="parameter">">po</replaceable>e>/<replaceable class="parameter">database</replaceable>
</para> </para>
</listitem> </listitem>
</itemizedlist>
</itemizedlist> where:
where: <variablelist>
<varlistentry>
<term>
<replaceable class="parameter">host</replaceable>
</term>
<listitem>
<para>
The hostname of the server. Defaults to "localhost".
</para>
</listitem>
</varlistentry>
<variablelist> <varlistentry>
<varlistentry> <term>
<term> <replaceable class="parameter">port</replaceable>
<replaceable class="parameter">host</replaceable> </term>
</term> <listitem>
<listitem> <para>
<para> The port number the server is listening on. Defaults to the Postgres
The hostname of the server. Defaults to "localhost". standard port number (5432).
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<replaceable class="parameter">port</replaceable> <replaceable class="parameter">database</replaceable>
</term> </term>
<listitem> <listitem>
<para> <para>
The port number the server is listening on. Defaults to the Postgres The database name.
standard port number (5432). </para>
</para> </listitem>
</listitem> </varlistentry>
</varlistentry> </variablelist>
</para>
<varlistentry> <para>
<term> To connect, you need to get a Connection instance from
<replaceable class="parameter">database</replaceable> <acronym>JDBC</acronym>. To do this,
</term> you would use the DriverManager.getConnection() method:
<listitem>
<para>
The database name.
</para>
</listitem>
</varlistentry>
</variablelist> <programlisting>
</para>
<para>
To connect, you need to get a Connection instance from
<acronym>JDBC</acronym>. To do this,
you would use the DriverManager.getConnection() method:
</para>
<para>
Connection db = DriverManager.getConnection(url,user,pwd); Connection db = DriverManager.getConnection(url,user,pwd);
</para> </programlisting>
</sect1> </para>
</sect1>
<sect1> <sect1>
<title>Issuing a Query and Processing the Result</title> <title>Issuing a Query and Processing the Result</title>
<para> <para>
Any time you want to issue SQL statements to the database, you require a Any time you want to issue SQL statements to the database, you require a
Statement instance. Once you have a Statement, you can use the executeQuery() Statement instance. Once you have a Statement, you can use the executeQuery()
method to issue a query. This will return a ResultSet instance, which contains method to issue a query. This will return a ResultSet instance, which contains
the entire result. the entire result.
</para> </para>
<sect2> <sect2>
<title>Using the Statement Interface</title> <title>Using the Statement Interface</title>
<para> <para>
The following must be considered when using the Statement interface: The following must be considered when using the Statement interface:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
You can use a Statement instance as many times as you want. You could You can use a Statement instance as many times as you want. You could
create one as soon as you open the connection, and use it for the connections create one as soon as you open the connection, and use it for the connections
lifetime. You have to remember that only one ResultSet can exist per Statement. lifetime. You have to remember that only one ResultSet can exist per Statement.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
If you need to perform a query while processing a ResultSet, you can If you need to perform a query while processing a ResultSet, you can
simply create and use another Statement. simply create and use another Statement.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
If you are using Threads, and several are using the database, you must If you are using Threads, and several are using the database, you must
use a separate Statement for each thread. Refer to the sections covering use a separate Statement for each thread. Refer to the sections covering
Threads and Servlets later in this document if you are thinking of using them, Threads and Servlets later in this document if you are thinking of using them,
as it covers some important points. as it covers some important points.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Using the ResultSet Interface</title> <title>Using the ResultSet Interface</title>
<para> <para>
The following must be considered when using the ResultSet interface: The following must be considered when using the ResultSet interface:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Before reading any values, you must call <function>next()</function>. This returns true if Before reading any values, you must call <function>next()</function>. This returns true if
there is a result, but more importantly, it prepares the row for processing. there is a result, but more importantly, it prepares the row for processing.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
Under the <acronym>JDBC</acronym> spec, you should access a field only once. It's safest Under the <acronym>JDBC</acronym> spec, you should access a
to stick to this rule, although at the current time, the <application>Postgres</application> driver field only once. It's safest to stick to this rule, although
will allow you to access a field as many times as you want. at the current time, the <application>Postgres</application> driver
</para> will allow you to access a field as many times as you want.
</listitem> </para>
</listitem>
<listitem> <listitem>
<para> <para>
You must close a ResultSet by calling <function>close()</function> once you have finished with it. You must close a ResultSet by calling
</para> <function>close()</function> once you have finished with it.
</listitem> </para>
</listitem>
<listitem> <listitem>
<para> <para>
Once you request another query with the Statement used to create a Once you request another query with the Statement used to create a
ResultSet, the currently open instance is closed. ResultSet, the currently open instance is closed.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
<para> <para>
An example is as follows: An example is as follows:
<programlisting> <programlisting>
Statement st = db.createStatement(); Statement st = db.createStatement();
ResultSet rs = st.executeQuery("select * from mytable"); ResultSet rs = st.executeQuery("select * from mytable");
while(rs.next()) { while(rs.next()) {
@ -387,74 +388,97 @@ while(rs.next()) {
} }
rs.close(); rs.close();
st.close(); st.close();
</programlisting> </programlisting>
</para> </para>
</sect2> </sect2>
</sect1> </sect1>
<sect1> <sect1>
<title>Performing Updates</title> <title>Performing Updates</title>
<para> <para>
To perform an update (or any other SQL statement that does not return a To perform an update (or any other SQL statement that does not return a
result), you simply use the executeUpdate() method: result), you simply use the <function>executeUpdate()</function> method:
<programlisting> <programlisting>
st.executeUpdate("create table basic (a int2, b int2)"); st.executeUpdate("create table basic (a int2, b int2)");
</programlisting> </programlisting>
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
<title>Closing the Connection</title> <title>Closing the Connection</title>
<para> <para>
To close the database connection, simply call the close() method to the Connection: To close the database connection, simply call the close() method to the Connection:
<programlisting> <programlisting>
db.close(); db.close();
</programlisting> </programlisting>
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
<title>Using Large Objects</title> <title>Using Large Objects</title>
<para> <para>
In <application>Postgres</application>, In <application>Postgres</application>,
large objects (also known as <firstterm>blobs</firstterm>) are used to hold data in large objects (also known as <firstterm>blobs</firstterm>) are used to hold data in
the database that cannot be stored in a normal SQL table. They are stored as a the database that cannot be stored in a normal SQL table. They are stored as a
Table/Index pair, and are refered to from your own tables, by an OID value. Table/Index pair, and are referred to from your own tables by an OID value.
</para> </para>
<para> <para>
Now, there are you methods of using Large Objects. The first is the <important>
standard <acronym>JDBC</acronym> way, and is documented here. The other, uses our own extension <para>
to the api, which presents the libpq large object <acronym>API</acronym> to Java, providing even For <productname>Postgres</productname>, you must access large
better access to large objects than the standard. Internally, the driver uses objects within an SQL transaction. Although this has always been
the extension to provide large object support. true in principle, it was not strictly enforced until the
</para> release of v6.5. You would open a transaction by using the
<para> <function>setAutoCommit()</function> method with an input
In <acronym>JDBC</acronym>, the standard way to access them is using the getBinaryStream() parameter of <literal>false</literal>:
method in ResultSet, and setBinaryStream() method in PreparedStatement. These
methods make the large object appear as a Java stream, allowing you to use the
java.io package, and others, to manipulate the object.
</para>
<para> <programlisting>
For example, suppose Connection mycon;
you have a table containing the file name of an image, and a large object ...
containing that image: mycon.setAutoCommit(false);
... now use Large Objects
</programlisting>
</para>
</important>
</para>
<programlisting> <para>
Now, there are two methods of using Large Objects. The first is the
standard <acronym>JDBC</acronym> way, and is documented here. The
other, uses our own extension
to the api, which presents the libpq large object
<acronym>API</acronym> to Java, providing even
better access to large objects than the standard. Internally, the driver uses
the extension to provide large object support.
</para>
<para>
In <acronym>JDBC</acronym>, the standard way to access them is using the getBinaryStream()
method in ResultSet, and setBinaryStream() method in PreparedStatement. These
methods make the large object appear as a Java stream, allowing you to use the
java.io package, and others, to manipulate the object.
</para>
<para>
For example, suppose
you have a table containing the file name of an image, and a large object
containing that image:
<programlisting>
create table images (imgname name,imgoid oid); create table images (imgname name,imgoid oid);
</programlisting> </programlisting>
</para> </para>
<para> <para>
To insert an image, you would use: To insert an image, you would use:
<programlisting> <programlisting>
File file = new File("myimage.gif"); File file = new File("myimage.gif");
FileInputStream fis = new FileInputStream(file); FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("insert into images values (?,?)"); PreparedStatement ps = conn.prepareStatement("insert into images values (?,?)");
@ -463,20 +487,20 @@ ps.setBinaryStream(2,fis,file.length());
ps.executeUpdate(); ps.executeUpdate();
ps.close(); ps.close();
fis.close(); fis.close();
</programlisting> </programlisting>
</para> </para>
<para> <para>
Now in this example, setBinaryStream transfers a set number of bytes from a Now in this example, setBinaryStream transfers a set number of bytes from a
stream into a large object, and stores the OID into the field holding a stream into a large object, and stores the OID into the field holding a
reference to it. reference to it.
</para> </para>
<para> <para>
Retrieving an image is even easier (I'm using PreparedStatement here, but Retrieving an image is even easier (I'm using PreparedStatement here, but
Statement can equally be used): Statement can equally be used):
<programlisting> <programlisting>
PreparedStatement ps = con.prepareStatement("select oid from images where name=?"); PreparedStatement ps = con.prepareStatement("select oid from images where name=?");
ps.setString(1,"myimage.gif"); ps.setString(1,"myimage.gif");
ResultSet rs = ps.executeQuery(); ResultSet rs = ps.executeQuery();
@ -489,31 +513,33 @@ if(rs!=null) {
rs.close(); rs.close();
} }
ps.close(); ps.close();
</programlisting> </programlisting>
</para> </para>
<para> <para>
Now here you can see where the Large Object is retrieved as an InputStream. Now here you can see where the Large Object is retrieved as an InputStream.
You'll also notice that we close the stream before processing the next row in You'll also notice that we close the stream before processing the next row in
the result. This is part of the <acronym>JDBC</acronym> Specification, which states that any the result. This is part of the <acronym>JDBC</acronym> Specification, which states that any
InputStream returned is closed when ResultSet.next() or ResultSet.close() is called. InputStream returned is closed when ResultSet.next() or ResultSet.close() is called.
</para> </para>
</sect1> </sect1>
<sect1> <sect1>
<title><application>Postgres</application> Extensions to the <acronym>JDBC</acronym> <acronym>API</acronym></title> <title><application>Postgres</application> Extensions to the
<acronym>JDBC</acronym> <acronym>API</acronym></title>
<para> <para>
<application>Postgres</application> is an extensible database system. <application>Postgres</application> is an extensible database system.
You can add your own functions You can add your own functions
to the backend, which can then be called from queries, or even add your own to the backend, which can then be called from queries, or even add your own
data types. data types.
</para> </para>
<para>
Now, as these are facilities unique to us, we support them from Java, with <para>
a set of extension <acronym>API</acronym>'s. Some features within Now, as these are facilities unique to us, we support them from Java, with
the core of the standard driver a set of extension <acronym>API</acronym>'s. Some features within
actually use these extensions to implement Large Objects, etc. the core of the standard driver
actually use these extensions to implement Large Objects, etc.
<!-- <!--
************************************************************ ************************************************************
@ -2241,7 +2267,8 @@ java.lang.Object
public class PGobject extends Object implements Serializable, public class PGobject extends Object implements Serializable,
Cloneable Cloneable
This class is used to describe data types that are unknown by <acronym>JDBC</acronym> This class is used to describe data types that are unknown by
<acronym>JDBC</acronym>
Standard. Standard.
A call to postgresql.Connection permits a class that extends this A call to postgresql.Connection permits a class that extends this
class to be associated with a named type. This is how the class to be associated with a named type. This is how the
@ -2550,7 +2577,8 @@ while another one is receiving results, and this would be a bad thing
for the database engine. for the database engine.
PostgreSQL 6.4, brings thread safety to the entire driver. Standard PostgreSQL 6.4, brings thread safety to the entire driver. Standard
<acronym>JDBC</acronym> was thread safe in 6.3.x, but the Fastpath <acronym>API</acronym> wasn't. <acronym>JDBC</acronym> was thread safe in 6.3.x, but the Fastpath
<acronym>API</acronym> wasn't.
So, if your application uses multiple threads (which most decent ones So, if your application uses multiple threads (which most decent ones
would), then you don't have to worry about complex schemes to ensure would), then you don't have to worry about complex schemes to ensure
@ -2614,3 +2642,20 @@ document, and also includes precompiled drivers for v6.4, and earlier.
</para> </para>
</sect1> </sect1>
</chapter> </chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
--></book>