Add mention of transactions and large objects.
Still need the code updated for LO examples.
This commit is contained in:
parent
0655b1500f
commit
ee8d39a852
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue