# The PostgreSQL JDBC Interface

## Introduction

JDBC is a core API of Java 1.1 and later. It provides a standard set of interfaces to SQL-compliant databases.

PostgreSQL provides a type 4 JDBC driver. Type 4 indicates that the driver is written in Pure Java, and communicates in the database system's own network protocol. Because of this, the driver is platform independent; once compiled, the driver can be used on any system.

This manual is not intended as a complete guide to JDBC programming, but should help to get you started. For more information refer to the standard JDBC API documentation. Also, take a look at the examples included with the source.

## Setting up the JDBC Driver

This section describes the steps you need to take before you can write or run programs that use the JDBC interface.

### Getting the Driver

Precompiled versions of the driver can be downloaded from the PostgreSQL JDBC web site.

Alternatively you can build the driver from source, but you should only need to do this if you are making changes to the source code. To build the JDBC driver, you need Ant 1.5 or higher and a JDK. Ant is a special tool for building Java-based packages. It can be downloaded from the Ant web site.

If you have several Java compilers installed, it depends on the Ant configuration which one gets used. Precompiled Ant distributions are typically set up to read a file `.antrc` in the current user's home directory for configuration. For example, to use a different JDK than the default, this may work:

    JAVA_HOME=/usr/local/sun-jdk1.3
    JAVACMD=$JAVA_HOME/bin/java

To compile the driver simply run `ant` in the top level directory. The compiled driver will be placed in `jars/postgresql.jar`. The resulting driver will be built for the version of Java you are running. If you build with a 1.2 or 1.3 JDK you will build a version that supports the JDBC 2 specification, and finally if you build with a 1.4 or 5.0 JDK you will build a version that supports the JDBC 3 specification.

### Setting up the Class Path

To use the driver, the JAR archive (named `postgresql.jar` if you built from source, otherwise it will likely be named with the following convention: `postgresql-`[server version]`.`[buildnumber]`.jdbc`[JDBC version]`.jar`, for example `postgresql-8.0-310.jdbc3.jar`) needs to be included in the class path, either by putting it in the `CLASSPATH` environment variable, or by using flags on the `java` command line.

For instance, assume we have an application that uses the JDBC driver to access a database, and that application is installed as `/usr/local/lib/myapp.jar`. The PostgreSQL JDBC driver installed as `/usr/local/pgsql/share/java/postgresql.jar`. To run the application, we would use:

    export CLASSPATH=/usr/local/lib/myapp.jar:/usr/local/pgsql/share/java/postgresql.jar:.
    java MyApp

Loading the driver from within the application is covered in use.

### Preparing the Database Server for JDBC

Because Java does not support using unix sockets the PostgreSQL server must be configured to allow TCP/IP connections. Starting with server version 8.0 TCP/IP connections are allowed from `localhost`. To allow connections to other interfaces than the loopback interface, you must modify the `postgresql.conf` file's `listen_addresses` setting.

For server versions prior to 8.0 the server does not listen on any interface by default, and you must set `tcpip_socket = true` in the `postgresql.conf` file.

Once you have made sure the server is correctly listening for TCP/IP connections the next step is to verify that users are allowed to connect to the server. Client authentication is setup in `pg_hba.conf`. Refer to the main PostgreSQL documentation for details. The JDBC driver supports the `trust`, `ident`, `password`, `md5`, and `crypt` authentication methods.

### Creating a Database

When creating a database to be accessed via JDBC it is important to select an appropriate encoding for your data. Many other client interfaces do not care what data you send back and forth, and will allow you to do inappropriate things, but Java makes sure that your data is correctly encoded. Do not use a database that uses the `SQL_ASCII` encoding. This is not a real encoding and you will have problems the moment you store data in it that does not fit in the seven bit ASCII character set. If you do not know what your encoding will be or are otherwise unsure about what you will be storing the `UNICODE` encoding is a reasonable default to use.

## Initializing the Driver

This section describes how to load and initialize the JDBC driver in your programs.

### Importing JDBC

Any source that uses JDBC needs to import the `java.sql` package, using:

    import java.sql.*;

You should not import the `org.postgresql` package unless you are using not standard PostgreSQL extensions to the JDBC API.

### Loading the Driver

Before you can connect to a database, you need to load the driver. There are two methods available, and it depends on your code which is the best one to use.

In the first method, your code implicitly loads the driver using the `Class.forName()` method. For PostgreSQL, you would use:

    Class.forName("org.postgresql.Driver");

This will load the driver, and while loading, the driver will automatically register itself with JDBC.

The `forName()` method can throw a `ClassNotFoundException` if the driver is not available.

This is the most common method to use, but restricts your code to use just PostgreSQL. If your code may access another database system in the future, and you do not use any PostgreSQL-specific extensions, then the second method is advisable.

The second method passes the driver as a parameter to the JVM as it starts, using the `-D` argument. Example:

    java -Djdbc.drivers=org.postgresql.Driver example.ImageViewer

In this example, the JVM will attempt to load the driver as part of its initialization. Once done, the `ImageViewer` is started.

Now, this method is the better one to use because it allows your code to be used with other database packages without recompiling the code. The only thing that would also change is the connection URL, which is covered next.

One last thing: When your code then tries to open a `Connection`, and you get a No driver available `SQLException` being thrown, this is probably caused by the driver not being in the class path, or the value in the parameter not being correct.

### Connecting to the Database

With JDBC, a database is represented by a URL (Uniform Resource Locator). With PostgreSQL, this takes one of the following forms:

-     jdbc:postgresql:database

-     jdbc:postgresql://host/database

-     jdbc:postgresql://host:port/database

The parameters have the following meanings:

`host`

- The host name of the server. Defaults to `localhost`. To specify an IPv6 address your must enclose the `host` parameter with square brackets, for example:

      jdbc:postgresql://[::1]:5740/accounting

`port`

- The port number the server is listening on. Defaults to the PostgreSQL standard port number (5432).

`database`

- The database name.

To connect, you need to get a `Connection` instance from JDBC. To do this, you use the `DriverManager.getConnection()` method:

    Connection db = DriverManager.getConnection(url, username, password);

#### Connection Parameters

In addition to the standard connection parameters the driver supports a number of additional properties which can be used to specify additional driver behavior specific to PostgreSQL. These properties may be specified in either the connection URL or an additional `Properties` object parameter to `DriverManager.getConnection`. The following examples illustrate the use of both methods to establish a SSL connection.

    String url = "jdbc:postgresql://localhost/test";
    Properties props = new Properties();
    props.setProperty("user","fred");
    props.setProperty("password","secret");
    props.setProperty("ssl","true");
    Connection conn = DriverManager.getConnection(url, props);

    String url = "jdbc:postgresql://localhost/test?user=fred&password=secret&ssl=true";
    Connection conn = DriverManager.getConnection(url);

`user` = `String`

- The database user on whose behalf the connection is being made.

`password` = `String`

- The database user's password.

`ssl`

- Connect using SSL. The driver must have been compiled with SSL support. This property does not need a value associated with it. The mere presence of it specifies a SSL connection. However, for compatibility with future versions, the value "true" is preferred. For more information see ssl.

`sslfactory` = `String`

- The provided value is a class name to use as the `SSLSocketFactory` when establishing a SSL connection. For more information see ssl-factory.

`sslfactoryarg` = `String`

- This value is an optional argument to the constructor of the `sslfactory` class provided above. For more information see ssl-factory.

`compatible` = `String`

- Act like an older version of the driver to retain compatibility with older applications. At the moment this controls two driver behaviors: the handling of binary data fields, and the handling of parameters set via `setString()`

  Older versions of the driver used this property to also control the protocol used to connect to the backend. This is now controlled by the `protocolVersion` property.

  Information on binary data handling is detailed in binary-data. To force the use of Large Objects set the compatible property to 7.1.

  When `compatible` is set to `7.4` or below, the default for the `stringtype` parameter is changed to `unspecified`.

`protocolVersion` = `String`

- The driver supports both the V2 and V3 frontend/backend protocols. The V3 protocol was introduced in 7.4 and the driver will by default try to connect using the V3 protocol, if that fails it will fall back to the V2 protocol. If the protocolVersion property is specified, the driver will try only the specified protocol (which should be either "2" or "3"). Setting protocolVersion to "2" may be used to avoid the failed attempt to use the V3 protocol when connecting to a version 7.3 or earlier server, or to force the driver to use the V2 protocol despite connecting to a 7.4 or greater server.

`loglevel` = `int`

- Set the amount of logging information printed to the DriverManager's current value for LogStream or LogWriter. It currently supports values of `org.postgresql.Driver.DEBUG` (2) and `org.postgresql.Driver.INFO` (1). `INFO` will log very little information while `DEBUG` will produce significant detail. This property is only really useful if you are a developer or are having problems with the driver.

`charSet` = `String`

- The character set to use for data sent to the database or recieved from the database. This property is only relevent for server versions less than or equal to 7.2. The 7.3 release was the first with multibyte support compiled by default and the driver uses its character set translation facilities instead of trying to do it itself.

`allowEncodingChanges` = `boolean`

- When using the V3 protocol the driver monitors changes in certain server configuration parameters that should not be touched by end users. The `client_encoding` setting is set by the driver and should not be altered. If the driver detects a change it will abort the connection. There is one legitimate exception to this behavior though, using the `COPY` command on a file residing on the server's filesystem. The only means of specifying the encoding of this file is by altering the `client_encoding` setting. The JDBC team considers this a failing of the `COPY` command and hopes to provide an alternate means of specifying the encoding in the future, but for now there is this URL parameter. Enable this only if you need to override the client encoding when doing a copy.

`logUnclosedConnections` = `boolean`

- Clients may leak `Connection` objects by failing to call its `close()` method. Eventually these objects will be garbage collected and the `finalize()` method will be called which will close the `Connection` if caller has neglected to do this himself. The usage of a finalizer is just a stopgap solution. To help developers detect and correct the source of these leaks the `logUnclosedConnections` URL parameter has been added. It captures a stacktrace at each `Connection` opening and if the `finalize()` method is reached without having been closed the stacktrace is printed to the log.

`prepareThreshold` = `int`

- Determine the number of `PreparedStatement` executions required before switching over to use server side prepared statements. The default is five, meaning start using server side prepared statements on the fifth execution of the same `PreparedStatement` object. More information on server side prepared statements is available in server-prepare.

`loginTimeout` = `int`

- Specify how long to wait for establishment of a database connection. The timeout is specified in seconds.

`stringtype` = `String`

- Specify the type to use when binding `PreparedStatement` parameters set via `setString()`. If `stringtype` is set to `varchar` (the default), such parameters will be sent to the server as `varchar` parameters. If `stringtype` is set to `unspecified`, parameters will be sent to the server as untyped values, and the server will attempt to infer an appropriate type. This is useful if you have an existing application that uses `setString()` to set parameters that are actually some other type, such as integers, and you are unable to change the application to use an appropriate method such as `setInt()`.

## Using SSL

### Configuring the Server

Configuring the PostgreSQL server for SSL is covered in the main documentation, so it will not be repeated here. Before trying to access your SSL enabled server from Java, make sure you can get to it via `psql`. You should see output like the following if you have established a SSL connnection.

    $ ./bin/psql -h localhost
    Welcome to psql 8.0.0rc5, the PostgreSQL interactive terminal.

    Type:  \copyright for distribution terms
           \h for help with SQL commands
           \? for help with psql commands
           \g or terminate with semicolon to execute query
           \q to quit

    SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)

    jurka=#

### Configuring the Client

Unlike psql and other libpq based programs the JDBC driver does server certificate validation by default. This means that when establishing a SSL connection the JDBC driver will validate the server's identity preventing "man in the middle" attacks. It does this by checking that the server certificate is signed by a trusted authority. If you have a certificate signed by a global certificate authority (CA), there is nothing further to do because Java comes with copies of the most common CA's certificates. If you are dealing with a self-signed certificate though, you need to make this available to the Java client to enable it to validate the server's certificate.

Only the JDBC 3 driver supports SSL. The 1.4 JDK was the first version to come bundled with SSL support. Previous JDK versions that wanted to use SSL could make use of the additional JSSE library, but it does not support the full range of features utilized by the PostgreSQL JDBC driver.

To make the server certificate available to Java, the first step is to convert it to a form Java understands.

    openssl x509 -in server.crt -out server.crt.der -outform der

From here the easiest thing to do is import this certificate into Java's system truststore.

    keytool -keystore $JAVA_HOME/lib/security/cacerts -alias postgresql -import -file server.crt.der

The default password for the cacerts keystore is `changeit`. The alias to postgesql is not important and you may select any name you desire.

If you do not have access to the system cacerts truststore you can create your own truststore.

    keytool -keystore mystore -alias postgresql -import -file server.crt.der

When starting your Java application you must specify this keystore and password to use.

    java -Djavax.net.ssl.trustStore=mystore -Djavax.net.ssl.trustStorePassword=mypassword com.mycompany.MyApp

In the event of problems extra debugging information is available by adding `-Djavax.net.debug=ssl` to your command line.

To instruct the JDBC driver to try and establish a SSL connection you must add the connection URL parameter `ssl=true`.

#### Using SSL without Certificate Validation

In some situations it may not be possible to configure your Java environment to make the server certificate available, for example in an applet. For a large scale deployment it would be best to get a certificate signed by recognized certificate authority, but that is not always an option. The JDBC driver provides an option to establish a SSL connection without doing any validation, but please understand the risk involved before enabling this option.

A non-validating connection is established via a custom `SSLSocketFactory` class that is provided with the driver. Setting the connection URL parameter `sslfactory=org.postgresql.ssl.NonValidatingFactory` will turn off all SSL validation.

### Custom SSLSocketFactory

PostgreSQL provides a way for developers to customize how a SSL connection is established. This may be used to provide a custom certificate source or other extensions by allowing the developer to create their own `SSLContext` instance. The connection URL parameters `sslfactory` and `sslfactoryarg` allow the user to specify which custom class to use for creating the `SSLSocketFactory`. The class name specified by `sslfactory` must extend `javax.net.ssl.SSLSocketFactory` and be available to the driver's classloader. This class must have a zero argument constructor or a single argument constructor taking a `String` argument. This argument may optionally be supplied by `sslfactoryarg`.

Information on how to actually implement such a class is beyond the scope of this documentation. Places to look for help are the JSSE Reference Guide and the source to the `NonValidatingFactory` provided by the JDBC driver.

The Java SSL API is not very well known to the JDBC driver developers and we would be interested in any interesting and generally useful extensions that you have implemented using this mechanism. Specifically it would be nice to be able to provide client certificates to be validated by the server.

## Issuing a Query and Processing the Result

Any time you want to issue SQL statements to the database, you require a `Statement` or `PreparedStatement` instance. Once you have a `Statement` or `PreparedStatement`, you can use issue a query. This will return a `ResultSet` instance, which contains the entire result (see query-with-cursor here for how to alter this behaviour). query-example illustrates this process.

### Processing a Simple Query in JDBC

This example will issue a simple query and print out the first column of each row using a `Statement`.

    Statement st = conn.createStatement();
    ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500");
    while (rs.next()) {
        System.out.print("Column 1 returned ");
        System.out.println(rs.getString(1));
    }
    rs.close();
    st.close();

This example issues the same query as before but uses a `PreparedStatement` and a bind value in the query.

    int foovalue = 500;
    PreparedStatement st = conn.prepareStatement("SELECT * FROM mytable WHERE columnfoo = ?");
    st.setInt(1, foovalue);
    ResultSet rs = st.executeQuery();
    while (rs.next()) {
        System.out.print("Column 1 returned ");
        System.out.println(rs.getString(1));
    }
    rs.close();
    st.close();

### Getting results based on a cursor

By default the driver collects all the results for the query at once. This can be inconvenient for large data sets so the JDBC driver provides a means of basing a `ResultSet` on a database cursor and only fetching a small number of rows.

A small number of rows are cached on the client side of the connection and when exhausted the next block of rows is retrieved by repositioning the cursor.

Cursor based `ResultSets` cannot be used in all situations. There a number of restrictions which will make the driver silently fall back to fetching the whole `ResultSet` at once.

- The connection to the server must be using the V3 protocol. This is the default for (and is only supported by) server versions 7.4 and later.

- The `Connection` must not be in autocommit mode. The backend closes cursors at the end of transactions, so in autocommit mode the backend will have closed the cursor before anything can be fetched from it.

- The `Statement` must be created with a `ResultSet` type of `ResultSet.TYPE_FORWARD_ONLY`. This is the default, so no code will need to be rewritten to take advantage of this, but it also means that you cannot scroll backwards or otherwise jump around in the `ResultSet`.

- The query given must be a single statement, not multiple statements strung together with semicolons.

#### Setting fetch size to turn cursors on and off.

Changing code to cursor mode is as simple as setting the fetch size of the `Statement` to the appropriate size. Setting the fetch size back to 0 will cause all rows to be cached (the default behaviour).

    // make sure autocommit is off
    conn.setAutoCommit(false);
    Statement st = conn.createStatement();

    // Turn use of the cursor on.
    st.setFetchSize(50);
    ResultSet rs = st.executeQuery("SELECT * FROM mytable");
    while (rs.next()) {
       System.out.print("a row was returned.");
    }
    rs.close();

    // Turn the cursor off.
    st.setFetchSize(0);
    rs = st.executeQuery("SELECT * FROM mytable");
    while (rs.next()) {
       System.out.print("many rows were returned.");
    }
    rs.close();

    // Close the statement.
    st.close();

### Using the `Statement` or `PreparedStatement` Interface

The following must be considered when using the `Statement` or `PreparedStatement` interface:

- You can use a single `Statement` instance as many times as you want. You could create one as soon as you open the connection and use it for the connection's lifetime. But you have to remember that only one `ResultSet` can exist per `Statement` or `PreparedStatement` at a given time.

- If you need to perform a query while processing a `ResultSet`, you can simply create and use another `Statement`.

- If you are using threads, and several are using the database, you must use a separate `Statement` for each thread. Refer to thread if you are thinking of using threads, as it covers some important points.

- When you are done using the `Statement` or `PreparedStatement` you should close it.

### Using the `ResultSet` Interface

The following must be considered when using the `ResultSet` interface:

- Before reading any values, you must call `next()`. This returns true if there is a result, but more importantly, it prepares the row for processing.

- You must close a `ResultSet` by calling `close()` once you have finished using it.

- Once you make another query with the `Statement` used to create a `ResultSet`, the currently open `ResultSet` instance is closed automatically.

### Performing Updates

To change data (perform an `INSERT`, `UPDATE`, or `DELETE`) you use the `executeUpdate()` method. This method is similar to the method `executeQuery()` used to issue a `SELECT` statement, but it doesn't return a `ResultSet`; instead it returns the number of rows affected by the `INSERT`, `UPDATE`, or `DELETE` statement. delete-example illustrates the usage.

#### Deleting Rows in JDBC

This example will issue a simple `DELETE` statement and print out the number of rows deleted.

    int foovalue = 500;
    PreparedStatement st = conn.prepareStatement("DELETE FROM mytable WHERE columnfoo = ?");
    st.setInt(1, foovalue);
    int rowsDeleted = st.executeUpdate();
    System.out.println(rowsDeleted + " rows deleted");
    st.close();

### Creating and Modifying Database Objects

To create, modify or drop a database object like a table or view you use the `execute()` method. This method is similar to the method `executeQuery()`, but it doesn't return a result. drop-table-example illustrates the usage.

#### Dropping a Table in JDBC

This example will drop a table.

    Statement st = conn.createStatement();
    st.execute("DROP TABLE mytable");
    st.close();

## Calling Stored Functions

### Calling a built in stored function

This example shows how to call a PostgreSQL built in function, `upper`, which simply converts the supplied string argument to uppercase.

    CallableStatement upperProc = conn.prepareCall("{ ? = call upper( ? ) }");
    upperProc.registerOutParameter(1, Types.VARCHAR);
    upperProc.setString(2, "lowercase to uppercase");
    upperProc.execute();
    String upperCased = upperProc.getString(1);
    upperProc.close();

### Obtaining a `ResultSet` from a stored function

PostgreSQL's stored functions can return results in two different ways. The function may return either a `refcursor` value or a `SETOF` some datatype. Depending on which of these return methods are used determines how the function should be called.

#### From a Function Returing `SETOF` type

Functions that return data as a set should not be called via the `CallableStatement` interface, but instead should use the normal `Statement` or `PreparedStatement` interfaces.

##### Getting `SETOF` type values from a function

    Statement stmt = conn.createStatement();
    stmt.execute("CREATE OR REPLACE FUNCTION setoffunc() RETURNS SETOF int AS "
    		+ "' SELECT 1 UNION SELECT 2;' LANGUAGE sql");
    ResultSet rs = stmt.executeQuery("SELECT * FROM setoffunc()");
    while (rs.next()) {
        // do something
    }
    rs.close();
    stmt.close();

#### From a Function Returing a `refcursor`

When calling a function that returns a `refcursor` you must cast the return type of `getObject` to a `ResultSet`

One notable limitation of the current support for a `ResultSet` created from a `refcursor` is that even though it is a cursor backed `ResultSet`, all data will be retrieved and cached on the client. The `Statement` fetch size parameter described in query-with-cursor is ignored. This limitation is a deficiency of the JDBC driver, not the server, and it is technically possible to remove it, we just haven't found the time.

##### Getting `refcursor` Value From a Function

    // Setup function to call.
    Statement stmt = conn.createStatement();
    stmt.execute("CREATE OR REPLACE FUNCTION refcursorfunc() RETURNS refcursor AS '"
    		+ " DECLARE "
    		+ "    mycurs refcursor; "
    		+ " BEGIN "
    		+ "    OPEN mycurs FOR SELECT 1 UNION SELECT 2; "
    		+ "    RETURN mycurs; "
    		+ " END;' language plpgsql");
    stmt.close();

    // We must be inside a transaction for cursors to work.
    conn.setAutoCommit(false);

    // Procedure call.
    CallableStatement proc = conn.prepareCall("{ ? = call refcursorfunc() }");
    proc.registerOutParameter(1, Types.Other);
    proc.execute();
    ResultSet results = (ResultSet) proc.getObject(1);
    while (results.next()) {
        // do something with the results...
    }
    results.close();
    proc.close();

It is also possible to treat the `refcursor` return value as a cursor name directly. To do this, use the `getString` of `ResultSet`. With the underlying cursor name, you are free to directly use cursor commands on it, such as `FETCH` and `MOVE`.

##### Treating `refcursor` as a cursor name

    conn.setAutoCommit(false);
    CallableStatement proc = conn.prepareCall("{ ? = call refcursorfunc() }");
    proc.registerOutParameter(1, Types.Other);
    proc.execute();
    String cursorName = proc.getString(1);
    proc.close();

## Storing Binary Data

PostgreSQL provides two distinct ways to store binary data. Binary data can be stored in a table using the data type `bytea` or by using the Large Object feature which stores the binary data in a separate table in a special format and refers to that table by storing a value of type `oid` in your table.

In order to determine which method is appropriate you need to understand the limitations of each method. The `bytea` data type is not well suited for storing very large amounts of binary data. While a column of type `bytea` can hold up to 1 GB of binary data, it would require a huge amount of memory to process such a large value. The Large Object method for storing binary data is better suited to storing very large values, but it has its own limitations. Specifically deleting a row that contains a Large Object reference does not delete the Large Object. Deleting the Large Object is a separate operation that needs to be performed. Large Objects also have some security issues since anyone connected to the database can view and/or modify any Large Object, even if they don't have permissions to view/update the row containing the Large Object reference.

Version 7.2 was the first release of the JDBC driver that supports the `bytea` data type. The introduction of this functionality in 7.2 has introduced a change in behavior as compared to previous releases. Since 7.2, the methods `getBytes()`, `setBytes()`, `getBinaryStream()`, and `setBinaryStream()` operate on the `bytea` data type. In 7.1 and earlier, these methods operated on the `oid` data type associated with Large Objects. It is possible to revert the driver back to the old 7.1 behavior by setting the property `compatible` on the `Connection` object to the value `7.1`. More details on connection properties are available in connection-parameters.

To use the `bytea` data type you should simply use the `getBytes()`, `setBytes()`, `getBinaryStream()`, or `setBinaryStream()` methods.

To use the Large Object functionality you can use either the `LargeObject` class provided by the PostgreSQL JDBC driver, or by using the `getBLOB()` and `setBLOB()` methods.

You must access Large Objects within an SQL transaction block. You can start a transaction block by calling `setAutoCommit(false)`.

binary-data-example contains some examples on how to process binary data using the PostgreSQL JDBC driver.

### Processing Binary Data in JDBC

For example, suppose you have a table containing the file names of images and you also want to store the image in a `bytea` column:

    CREATE TABLE images (imgname text, img bytea);

To insert an image, you would use:

    File file = new File("myimage.gif");
    FileInputStream fis = new FileInputStream(file);
    PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)");
    ps.setString(1, file.getName());
    ps.setBinaryStream(2, fis, (int)file.length());
    ps.executeUpdate();
    ps.close();
    fis.close();

Here, `setBinaryStream()` transfers a set number of bytes from a stream into the column of type `bytea`. This also could have been done using the `setBytes()` method if the contents of the image was already in a `byte[]`.

The length parameter to `setBinaryStream` must be correct. There is no way to indicate that the stream is of unknown length. If you are in this situation, you must read the stream yourself into temporary storage and determine the length. Now with the correct length you may send the data from temporary storage on to the driver.

Retrieving an image is even easier. (We use `PreparedStatement` here, but the `Statement` class can equally be used.)

    PreparedStatement ps = conn.prepareStatement("SELECT img FROM images WHERE imgname = ?");
    ps.setString(1, "myimage.gif");
    ResultSet rs = ps.executeQuery();
    while (rs.next()) {
        byte[] imgBytes = rs.getBytes(1);
        // use the data in some way here
    }
    rs.close();
    ps.close();

Here the binary data was retrieved as an `byte[]`. You could have used a `InputStream` object instead.

Alternatively you could be storing a very large file and want to use the `LargeObject` API to store the file:

    CREATE TABLE imageslo (imgname text, imgoid oid);

To insert an image, you would use:

    // All LargeObject API calls must be within a transaction block
    conn.setAutoCommit(false);

    // Get the Large Object Manager to perform operations with
    LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

    // Create a new large object
    int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);

    // Open the large object for writing
    LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);

    // Now open the file
    File file = new File("myimage.gif");
    FileInputStream fis = new FileInputStream(file);

    // Copy the data from the file to the large object
    byte buf[] = new byte[2048];
    int s, tl = 0;
    while ((s = fis.read(buf, 0, 2048)) > 0) {
        obj.write(buf, 0, s);
        tl += s;
    }

    // Close the large object
    obj.close();

    // Now insert the row into imageslo
    PreparedStatement ps = conn.prepareStatement("INSERT INTO imageslo VALUES (?, ?)");
    ps.setString(1, file.getName());
    ps.setInt(2, oid);
    ps.executeUpdate();
    ps.close();
    fis.close();

    // Finally, commit the transaction.
    conn.commit();

Retrieving the image from the Large Object:

    // All LargeObject API calls must be within a transaction block
    conn.setAutoCommit(false);

    // Get the Large Object Manager to perform operations with
    LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();

    PreparedStatement ps = conn.prepareStatement("SELECT imgoid FROM imageslo WHERE imgname = ?");
    ps.setString(1, "myimage.gif");
    ResultSet rs = ps.executeQuery();
    while (rs.next()) {
        // Open the large object for reading
        int oid = rs.getInt(1);
        LargeObject obj = lobj.open(oid, LargeObjectManager.READ);

        // Read the data
        byte buf[] = new byte[obj.size()];
        obj.read(buf, 0, obj.size());
        // Do something with the data read here

        // Close the object
        obj.close();
    }
    rs.close();
    ps.close();

    // Finally, commit the transaction.
    conn.commit();

## JDBC escapes

The JDBC specification (like the ODBC specification) acknowledges the fact that some vendor specific SQL may be required for certain RDBMS features. To aid developers in writing portable JDBC applications across multiple database products, a special escape syntax is used to specify the generic commands the developer wants to be run. The JDBC driver translates these escape sequences into native syntax for its specific database. For more information consult the section 4.1.5 from the JDBC Technology Guide (bundled with the Sun JRE documentation) and the section 13.4 from the JDBC 3.0 specification.

The parsing of the sql statements for these escapes can be disabled using `Statement.setEscapeProcessing(false)`.

`Connection.nativeSQL(String sql)` provides another way to have escapes processed. It translates the given SQL to a SQL suitable for the PostgreSQL backend.

### Using jdbc escapes

To use the JDBC escapes, you simply write your SQL replacing date/time literal values, outer join and functions by the JDBC escape syntax. For example :

    ResultSet rs = st.executeQuery("SELECT {fn week({d '2005-01-24'})}");

is the portable version for

    ResultSet rs = st.executeQuery("SELECT extract(week from DATE '2005-01-24')");

### Escape for like escape character

You can specify which escape character to use in strings comparison (with `LIKE`) to protect wildcards characters ('%' and '_') by adding the following escape : `{escape 'escape-character'}`. The driver supports this only at the end of the comparison expression.

For example, you can compare string values using '|' as escape character to protect '_' :

    rs = stmt.executeQuery("select str2 from comparisontest where str1 like '|_abcd' {escape '|'} ");

### Escape for outer joins

You can specify outer joins using the following syntax: `{oj table (LEFT|RIGHT|FULL) OUTER JOIN (table | outer-join) ON search-condition }`

For example :

    rs = stmt.executeQuery( "select * from {oj a left outer join b on (a.i=b.i)} ");

### Date-time escapes

The JDBC specification defines escapes for specifying date, time and timestamp values which are supported by the driver.

date

- `{d 'yyyy-mm-dd'}` which is translated to `DATE 'yyyy-mm-dd'`

time

- `{t 'hh:mm:ss'}` which is translated to `TIME 'hh:mm:ss'`

timestamp

- `{ts 'yyyy-mm-dd hh:mm:ss.f...'}` which is translated to `TIMESTAMP 'yyyy-mm-dd hh:mm:ss.f'` The fractional seconds (.f...) portion of the TIMESTAMP can be omitted.

### Escaped scalar functions

The JDBC specification defines functions with an escape call syntax : `{fn function_name(arguments)}`. The following tables show which functions are supported by the PostgresSQL driver. The driver supports the nesting and the mixing of escaped functions and escaped values. The appendix C of the JDBC specification describes the functions.

Some functions in the following tables are translated but not reported as supported because they are duplicating or changing ther order of the arguments. While this is harmless for literal values or columns, it will cause problems when using prepared statements. For example "`{fn right(?,?)}`" will be translated to "`substring(? from (length(?)+1-?))`". As you can see the translated SQL requires more parameters than before the translation but the driver will not automatically handle this.

### Supported escaped numeric functions

function | reported as supported | translation | comments
abs(arg1) | yes | abs(arg1) |
acos(arg1) | yes | acos(arg1) |
asin(arg1) | yes | asin(arg1) |
atan(arg1) | yes | atan(arg1) |
atan2(arg1,arg2) | yes | atan2(arg1,arg2) |
ceiling(arg1) | yes | ceil(arg1) |
cos(arg1) | yes | cos(arg1) |
cot(arg1) | yes | cot(arg1) |
degrees(arg1) | yes | degrees(arg1) |
exp(arg1) | yes | exp(arg1) |
floor(arg1) | yes | floor(arg1) |
log(arg1) | yes | ln(arg1) |
log10(arg1) | yes | log(arg1) |
mod(arg1,arg2) | yes | mod(arg1,arg2) |
pi(arg1) | yes | pi(arg1) |
power(arg1,arg2) | yes | pow(arg1,arg2) |
radians(arg1) | yes | radians(arg1) |
rand() | yes | random() |
rand(arg1) | yes | setseed(arg1)*0+random() | The seed is initialized with the given argument and a new randow value is returned.
round(arg1,arg2) | yes | round(arg1,arg2) |
sign(arg1) | yes | sign(arg1) |
sin(arg1) | yes | sin(arg1) |
sqrt(arg1) | yes | sqrt(arg1) |
tan(arg1) | yes | tan(arg1) |
truncate(arg1,arg2) | yes | trunc(arg1,arg2) |

### Supported escaped string functions

function | reported as supported | translation | comments
ascii(arg1) | yes | ascii(arg1) |
char(arg1) | yes | chr(arg1) |
concat(arg1,arg2...) | yes | (arg1||arg2...) | The JDBC specification only require the two arguments version, but supporting more arguments was so easy...
insert(arg1,arg2,arg3,arg4) | no | overlay(arg1 placing arg4 from arg2 for arg3) | This function is not reported as supported since it changes the order of the arguments which can be a problem (for prepared statements by example).
lcase(arg1) | yes | lower(arg1) |
left(arg1,arg2) | yes | substring(arg1 for arg2) |
length(arg1) | yes | length(trim(trailing from arg1)) |
locate(arg1,arg2) | no | position(arg1 in arg2) |
locate(arg1,arg2,arg3) | no | (arg2*sign(position(arg1 in substring(arg2 from arg3)+position(arg1 in substring(arg2 from arg3)) | Not reported as supported since the three arguments version duplicate and change the order of the arguments.
ltrim(arg1) | yes | trim(leading from arg1) |
repeat(arg1,arg2) | yes | repeat(arg1,arg2) |
replace(arg1,arg2,arg3) | yes | replace(arg1,arg2,arg3) | Only reported as supported by 7.3 and above servers.
right(arg1,arg2) | no | substring(arg1 from (length(arg1)+1-arg2)) | Not reported as supported since arg2 is duplicated.
rtrim(arg1) | yes | trim(trailing from arg1) |
space(arg1) | yes | repeat(' ',arg1) |
substring(arg1,arg2) | yes | substr(arg1,arg2) |
substring(arg1,arg2,arg3) | yes | substr(arg1,arg2,arg3) |
ucase(arg1) | yes | upper(arg1) |
soundex(arg1) | no | soundex(arg1) | Not reported as supported since it requires the fuzzystrmatch contrib module.
difference(arg1,arg2) | no | difference(arg1,arg2) | Not reported as supported since it requires the fuzzystrmatch contrib module.

### Supported escaped date/time functions

function | reported as supported | translation | comments
curdate() | yes | current_date |
curtime() | yes | current_time |
dayname(arg1) | yes | to_char(arg1,'Day') |
dayofmonth(arg1) | yes | extract(day from arg1) |
dayofweek(arg1) | yes | extract(dow from arg1)+1 | We must add 1 to be in the expected 1-7 range.
dayofyear(arg1) | yes | extract(doy from arg1) |
hour(arg1) | yes | extract(hour from arg1) |
minute(arg1) | yes | extract(minute from arg1) |
month(arg1) | yes | extract(month from arg1) |
monthname(arg1) | yes | to_char(arg1,'Month') |
now() | yes | now() |
quarter(arg1) | yes | extract(quarter from arg1) |
second(arg1) | yes | extract(second from arg1) |
week(arg1) | yes | extract(week from arg1) |
year(arg1) | yes | extract(year from arg1) |
timestampadd(argIntervalType,argCount,argTimeStamp) | yes | ('(interval according to argIntervalType and argCount)'+argTimeStamp) | an argIntervalType value of `SQL_TSI_FRAC_SECOND` is not implemented since backend does not support it
timestampdiff(argIntervalType,argTimeStamp1,argTimeStamp2) | not | extract((interval according to argIntervalType) from argTimeStamp2-argTimeStamp1 ) | only an argIntervalType value of `SQL_TSI_FRAC_SECOND`,`SQL_TSI_FRAC_MINUTE`,`SQL_TSI_FRAC_HOUR` or `SQL_TSI_FRAC_DAY` is supported

### Supported escaped misc functions

function | reported as supported | translation | comments
database() | yes | current_database() | Only reported as supported by 7.3 and above servers.
ifnull(arg1,arg2) | yes | coalesce(arg1,arg2) |
user() | yes | user |

## PostgreSQL Extensions to the JDBC API

PostgreSQL is an extensible database system. You can add your own functions to the server, which can then be called from queries, or even add your own data types. As these are facilities unique to PostgreSQL, we support them from Java, with a set of extension APIs. Some features within the core of the standard driver actually use these extensions to implement Large Objects, etc.

### Accessing the Extensions

To access some of the extensions, you need to use some extra methods in the `org.postgresql.PGConnection` class. In this case, you would need to case the return value of `Driver.getConnection()`. For example:

    Connection db = Driver.getConnection(url, username, password);
    // ...
    // later on
    Fastpath fp = ((org.postgresql.PGConnection)db).getFastpathAPI();

### Geometric Data Types

PostgreSQL has a set of data types that can store geometric features into a table. These include single points, lines, and polygons. We support these types in Java with the org.postgresql.geometric package. Please consult the Javadoc for the details of available classes and features metioned in reading.

#### Using the circle datatype from JDBC

    import java.sql.*;

    import org.postgresql.geometric.PGpoint;
    import org.postgresql.geometric.PGcircle;

    public class GeometricTest {

    	public static void main(String args[]) throws Exception {
    		Class.forName("org.postgresql.Driver");
    		String url = "jdbc:postgresql://localhost:5432/test";

    		Connection conn = DriverManager.getConnection(url,"test","");

    		Statement stmt = conn.createStatement();
    		stmt.execute("CREATE TEMP TABLE geomtest(mycirc circle)");
    		stmt.close();

    		insertCircle(conn);
    		retrieveCircle(conn);
    		conn.close();
    	}

    	private static void insertCircle(Connection conn) throws SQLException {

    		PGpoint center = new PGpoint(1, 2.5);
    		double radius = 4;
    		PGcircle circle = new PGcircle(center, radius);

    		PreparedStatement ps = conn.prepareStatement("INSERT INTO geomtest(mycirc) VALUES (?)");
    		ps.setObject(1, circle);
    		ps.executeUpdate();
    		ps.close();
    	}

    	private static void retrieveCircle(Connection conn) throws SQLException {
    		Statement stmt = conn.createStatement();
    		ResultSet rs = stmt.executeQuery("SELECT mycirc, area(mycirc) FROM geomtest");
    		rs.next();
    		PGcircle circle = (PGcircle)rs.getObject(1);
    		double area = rs.getDouble(2);

    		PGpoint center = circle.center;
    		double radius = circle.radius;

    		System.out.println("Center (X, Y) = (" + center.x + ", " + center.y + ")");
    		System.out.println("Radius = " + radius);
    		System.out.println("Area = " + area);
    	}
    }

### Large Objects

Large objects are supported in the standard JDBC specification. However, that interface is limited, and the API provided by PostgreSQL allows for random access to the objects contents, as if it was a local file.

The org.postgresql.largeobject package provides to Java the libpq C interface's large object API. It consists of two classes, `LargeObjectManager`, which deals with creating, opening and deleting large objects, and `LargeObject` which deals with an individual object. For an example usage of this API, please see binary-data-example.

### Listen / Notify

Listen and Notify provide a simple form of signal or interprocess communication mechanism for a collection of processes accessing the same PostgreSQL database. For more information on notifications consult the main server documentation. This section only deals with the JDBC specific aspects of notifications.

Standard `LISTEN`, `NOTIFY`, and `UNLISTEN` commands are issued via the standard `Statement` interface. To retrieve and process retrieved notifications the `Connection` must be cast to the PostgreSQL specific extension interface `PGConnection`. From there the `getNotifications()` method can be used to retrieve any outstanding notifications.

A key limitation of the JDBC driver is that it cannot receive asynchronous notifications and must poll the backend to check if any notifications were issued.

#### Receiving Notifications

    import java.sql.*;

    public class NotificationTest {

    	public static void main(String args[]) throws Exception {
    		Class.forName("org.postgresql.Driver");
    		String url = "jdbc:postgresql://localhost:5432/test";

    		// Create two distinct connections, one for the notifier
    		// and another for the listener to show the communication
    		// works across connections although this example would
    		// work fine with just one connection.
    		Connection lConn = DriverManager.getConnection(url,"test","");
    		Connection nConn = DriverManager.getConnection(url,"test","");

    		// Create two threads, one to issue notifications and
    		// the other to receive them.
    		Listener listener = new Listener(lConn);
    		Notifier notifier = new Notifier(nConn);
    		listener.start();
    		notifier.start();
    	}

    }

    class Listener extends Thread {

    	private Connection conn;
    	private org.postgresql.PGConnection pgconn;

    	Listener(Connection conn) throws SQLException {
    		this.conn = conn;
    		this.pgconn = (org.postgresql.PGConnection)conn;
    		Statement stmt = conn.createStatement();
    		stmt.execute("LISTEN mymessage");
    		stmt.close();
    	}

    	public void run() {
    		while (true) {
    			try {
    				// issue a dummy query to contact the backend
    				// and receive any pending notifications.
    				Statement stmt = conn.createStatement();
    				ResultSet rs = stmt.executeQuery("SELECT 1");
    				rs.close();
    				stmt.close();

    				org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
    				if (notifications != null) {
    					for (int i=0; i<notifications.length; i++) {
    						System.out.println("Got notification: " + notifications[i].getName());
    					}
    				}

    				// wait a while before checking again for new
    				// notifications
    				Thread.sleep(500);
    			} catch (SQLException sqle) {
    				sqle.printStackTrace();
    			} catch (InterruptedException ie) {
    				ie.printStackTrace();
    			}
    		}
    	}

    }

    class Notifier extends Thread {

    	private Connection conn;

    	public Notifier(Connection conn) {
    		this.conn = conn;
    	}

    	public void run() {
    		while (true) {
    			try {
    				Statement stmt = conn.createStatement();
    				stmt.execute("NOTIFY mymessage");
    				stmt.close();
    				Thread.sleep(2000);
    			} catch (SQLException sqle) {
    				sqle.printStackTrace();
    			} catch (InterruptedException ie) {
    				ie.printStackTrace();
    			}
    		}
    	}

    }

### Server Prepared Statements

The PostgreSQL server allows clients to compile sql statements that are expected to be reused to avoid the overhead of parsing and planning the statement for every execution. This functionality is available at the SQL level via PREPARE and EXECUTE beginning with server version 7.3, and at the protocol level beginning with server version 7.4, but as Java developers we really just want to use the standard `PreparedStatement` interface.

Previous versions of the driver used PREPARE and EXECUTE to implement server-prepared statements. This is supported on all server versions beginning with 7.3, but produced application-visible changes in query results, such as missing ResultSet metadata and row update counts. The current driver uses the V3 protocol-level equivalents which avoid these changes in query results, but the V3 protocol is only available beginning with server version 7.4. Enabling server-prepared statements will have no affect when connected to a 7.3 server or when explicitly using the V2 protocol to connect to a 7.4 server.

There are a number of ways to enable server side prepared statements depending on your application's needs. The general method is to set a threshold for a `PreparedStatement`. An internal counter keeps track of how many times the statement has been executed and when it reaches the threshold it will start to use server side prepared statements.

Server side prepared statements are planned only once by the server. This avoids the cost of replanning the query every time, but also means that the planner cannot take advantage of the particular parameter values used in a particular execution of the query. You should be cautious about enabling the use of server side prepared statements globally.

#### Using server side prepared statements

    import java.sql.*;

    public class ServerSidePreparedStatement
    {

    	public static void main(String args[]) throws Exception
    	{
    		Class.forName("org.postgresql.Driver");
    		String url = "jdbc:postgresql://localhost:5432/test";
    		Connection conn = DriverManager.getConnection(url,"test","");

    		PreparedStatement pstmt = conn.prepareStatement("SELECT ?");

    		// cast to the pg extension interface
    		org.postgresql.PGStatement pgstmt = (org.postgresql.PGStatement)pstmt;

    		// on the third execution start using server side statements
    		pgstmt.setPrepareThreshold(3);

    		for (int i=1; i<=5; i++)
    		{
    			pstmt.setInt(1,i);
    			boolean usingServerPrepare = pgstmt.isUseServerPrepare();
    			ResultSet rs = pstmt.executeQuery();
    			rs.next();
    			System.out.println("Execution: "+i+", Used server side: " + usingServerPrepare + ", Result: "+rs.getInt(1));
    			rs.close();
    		}

    		pstmt.close();
    		conn.close();
    	}
    }

Which produces the expected result of using server side prepared statements upon the third execution.

    Execution: 1, Used server side: false, Result: 1
    Execution: 2, Used server side: false, Result: 2
    Execution: 3, Used server side: true, Result: 3
    Execution: 4, Used server side: true, Result: 4
    Execution: 5, Used server side: true, Result: 5

The example shown above requires the programmer to use PostgreSQL specific code in a supposedly portable API which is not ideal. Also it sets the threshold only for that particular statement which is some extra typing if we wanted to use that threshold for every statement. Let's take a look at the other ways to set the threshold to enable server side prepared statements. There is already a hierarchy in place above a `PreparedStatement`, the `Connection` it was created from, and above that the source of the connection be it a `Datasource` or a URL. The server side prepared statement threshold can be set at any of these levels such that the value will be the default for all of it's children.

    // pg extension interfaces
    org.postgresql.PGConnection pgconn;
    org.postgresql.PGStatement pgstmt;

    // set a prepared statement threshold for connections created from this url
    String url = "jdbc:postgresql://localhost:5432/test?prepareThreshold=3";

    // see that the connection has picked up the correct threshold from the url
    Connection conn = DriverManager.getConnection(url,"test","");
    pgconn = (org.postgresql.PGConnection)conn;
    System.out.println(pgconn.getPrepareThreshold()); // Should be 3

    // see that the statement has picked up the correct threshold from the connection
    PreparedStatement pstmt = conn.prepareStatement("SELECT ?");
    pgstmt = (org.postgresql.PGStatement)pstmt;
    System.out.println(pgstmt.getPrepareThreshold()); // Should be 3

    // change the connection's threshold and ensure that new statements pick it up
    pgconn.setPrepareThreshold(5);
    PreparedStatement pstmt = conn.prepareStatement("SELECT ?");
    pgstmt = (org.postgresql.PGStatement)pstmt;
    System.out.println(pgstmt.getPrepareThreshold()); // Should be 5

## Using the Driver in a Multithreaded or a Servlet Environment

A problem with many JDBC drivers is that only one thread can use a `Connection` at any one time --- otherwise a thread could send a query while another one is receiving results, and this could cause severe confusion.

The PostgreSQL JDBC driver is thread safe. Consequently, if your application uses multiple threads then you do not have to worry about complex algorithms to ensure that only one thread uses the database at a time.

If a thread attempts to use the connection while another one is using it, it will wait until the other thread has finished its current operation. If the operation is a regular SQL statement, then the operation consists of sending the statement and retrieving any `ResultSet` (in full). If it is a fast-path call (e.g., reading a block from a large object) then it consists of sending and retrieving the respective data.

This is fine for applications and applets but can cause a performance problem with servlets. If you have several threads performing queries then each but one will pause. To solve this, you are advised to create a pool of connections. When ever a thread needs to use the database, it asks a manager class for a `Connection` object. The manager hands a free connection to the thread and marks it as busy. If a free connection is not available, it opens one. Once the thread has finished using the connection, it returns it to the manager which can then either close it or add it to the pool. The manager would also check that the connection is still alive and remove it from the pool if it is dead. The down side of a connection pool is that it increases the load on the server because a new session is created for each `Connection` object. It is up to you and your applications' requirements.

## Connection Pools and Data Sources

JDBC 2 introduced standard connection pooling features in an add-on API known as the JDBC 2.0 Optional Package (also known as the JDBC 2.0 Standard Extension). These features have since been included in the core JDBC 3 API. The PostgreSQL JDBC drivers support these features if it has been compiled with JDK 1.3.x in combination with the JDBC 2.0 Optional Package (JDBC 2), or with JDK 1.4 or higher (JDBC 3). Most application servers include the JDBC 2.0 Optional Package, but it is also available separately from the Sun JDBC download site.

### Overview

The JDBC API provides a client and a server interface for connection pooling. The client interface is `javax.sql.DataSource`, which is what application code will typically use to acquire a pooled database connection. The server interface is `javax.sql.ConnectionPoolDataSource`, which is how most application servers will interface with the PostgreSQL JDBC driver.

In an application server environment, the application server configuration will typically refer to the PostgreSQL `ConnectionPoolDataSource` implementation, while the application component code will typically acquire a `DataSource` implementation provided by the application server (not by PostgreSQL).

For an environment without an application server, PostgreSQL provides two implementations of `DataSource` which an application can use directly. One implementation performs connection pooling, while the other simply provides access to database connections through the `DataSource` interface without any pooling. Again, these implementations should not be used in an application server environment unless the application server does not support the `ConnectionPoolDataSource` interface.

### Application Servers: `ConnectionPoolDataSource`

PostgreSQL includes one implementation of `ConnectionPoolDataSource` named `org.postgresql.ds.PGConnectionPoolDataSource`.

JDBC requires that a `ConnectionPoolDataSource` be configured via JavaBean properties, shown in ds-cpds-props, so there are get and set methods for each of these properties.

### `ConnectionPoolDataSource` Configuration Properties

Property | Type | Description
`serverName` | `String` | PostgreSQL database server host name
`databaseName` | `String` | PostgreSQL database name
`portNumber` | `int` | TCP port which the PostgreSQL database server is listening on (or 0 to use the default port)
`user` | `String` | User used to make database connections
`password` | `String` | Password used to make database connections
`defaultAutoCommit` | `boolean` | Whether connections should have autocommit enabled or disabled when they are supplied to the caller. The default is `false`, to disable autocommit.

Many application servers use a properties-style syntax to configure these properties, so it would not be unusual to enter properties as a block of text. If the application server provides a single area to enter all the properties, they might be listed like this:

    serverName=localhost
    databaseName=test
    user=testuser
    password=testpassword

Or, if semicolons are used as separators instead of newlines, it could look like this:

    serverName=localhost;databaseName=test;user=testuser;password=testpassword

### Applications: `DataSource`

PostgreSQL includes two implementations of `DataSource` , as shown in ds-ds-imp. One that does pooling and the other that does not. The pooling implementation does not actually close connections when the client calls the `close` method, but instead returns the connections to a pool of available connections for other clients to use. This avoids any overhead of repeatedly opening and closing connections, and allows a large number of clients to share a small number of database connections.

The pooling data-source implementation provided here is not the most feature-rich in the world. Among other things, connections are never closed until the pool itself is closed; there is no way to shrink the pool. As well, connections requested for users other than the default configured user are not pooled. Its error handling sometimes cannot remove a broken connection from the pool. In general it is not recommended to use the PostgreSQL provided connection pool. Check your application server or check out the excellent jakarta commons DBCP project.

### `DataSource` Implementations

Pooling | Implementation Class
No | `org.postgresql.ds.PGSimpleDataSource`
Yes | `org.postgresql.ds.PGPoolingDataSource`

Both implementations use the same configuration scheme. JDBC requires that a `DataSource` be configured via JavaBean properties, shown in ds-ds-props, so there are get and set methods for each of these properties.

### `DataSource` Configuration Properties

Property | Type | Description
`serverName` | `String` | PostgreSQL database server host name
`databaseName` | `String` | PostgreSQL database name
`portNumber` | `int` | TCP port which the PostgreSQL database server is listening on (or 0 to use the default port)
`user` | `String` | User used to make database connections
`password` | `String` | Password used to make database connections

The pooling implementation requires some additional configuration properties, which are shown in ds-ds-xprops.

### Additional Pooling `DataSource` Configuration Properties

Property | Type | Description
`dataSourceName` | `String` | Every pooling `DataSource` must have a unique name.
`initialConnections` | `int` | The number of database connections to be created when the pool is initialized.
`maxConnections` | `int` | The maximum number of open database connections to allow. When more connections are requested, the caller will hang until a connection is returned to the pool.

ds-example shows an example of typical application code using a pooling `DataSource`.

#### `DataSource` Code Example

Code to initialize a pooling `DataSource` might look like this:

    PGPoolingDataSource source = new PGPoolingDataSource();
    source.setDataSourceName("A Data Source");
    source.setServerName("localhost");
    source.setDatabaseName("test");
    source.setUser("testuser");
    source.setPassword("testpassword");
    source.setMaxConnections(10);

Then code to use a connection from the pool might look like this. Note that it is critical that the connections are eventually closed. Else the pool will leak connections and will eventually lock all the clients out.

    Connection conn = null;
    try {
        conn = source.getConnection();
        // use connection
    } catch (SQLException e) {
        // log error
    } finally {
        if (con != null) {
            try { conn.close(); } catch (SQLException e) {}
        }
    }

### Tomcat setup

The postgresql.jar file must be placed in $CATALINA_HOME/common/lib in both Tomcat 4 and 5.

The absolute easiest way to set this up in either tomcat instance is to use the admin web application that comes with Tomcat, simply add the datasource to the context you want to use it in.

Setup for Tomcat 4 place the following inside the <Context> tag inside conf/server.xml

    <Resource name="jdbc/postgres" scope="Shareable" type="javax.sql.DataSource"/>
    <ResourceParams name="jdbc/postgres">
    	<parameter>
    		<name>validationQuery</name>
    		<value>select version();</value>
    	</parameter>
    	<parameter>
    		<name>url</name>
    		<value>jdbc:postgresql://localhost/davec</value>
    	</parameter>
    	<parameter>
    		<name>password</name>
    		<value>davec</value>
    	</parameter>
    	<parameter>
    		<name>maxActive</name>
    		<value>4</value>
    	</parameter>
    	<parameter>
    		<name>maxWait</name>
    		<value>5000</value>
    	</parameter>
    	<parameter>
    		<name>driverClassName</name>
    		<value>org.postgresql.Driver</value>
    	</parameter>
    	<parameter>
    		<name>username</name>
    		<value>davec</value>
    	</parameter>
    	<parameter>
    		<name>maxIdle</name>
    		<value>2</value>
    	</parameter>
    </ResourceParams>

Setup for Tomcat 5, you can use the above method, except that it goes inside the <DefaultContext> tag inside the <Host> tag. eg. <Host> ... <DefaultContext> ...

Alternatively there is a conf/Catalina/hostname/context.xml file. For example http://localhost:8080/servlet-example has a directory $CATALINA_HOME/conf/Catalina/localhost/servlet-example.xml file. Inside this file place the above xml inside the <Context> tag

Then you can use the following code to access the connection.

    import javax.naming.*;
    import javax.sql.*;
    import java.sql.*;
    public class DBTest
    {

    	String foo = "Not Connected";
    	int bar = -1;

    	public void init()
    	{

    		try
    		{
    			Context ctx = new InitialContext();
    			if(ctx == null )
    				throw new Exception("Boom - No Context");

    			// /jdbc/postgres is the name of the resource above
    			DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/postgres");

    			if (ds != null)
    			{
    				Connection conn = ds.getConnection();

    				if(conn != null)
    				{
    					foo = "Got Connection "+conn.toString();
    					Statement stmt = conn.createStatement();
    					ResultSet rst = stmt.executeQuery("select id, foo, bar from testdata");
    					if(rst.next()) {
    						foo=rst.getString(2);
    						bar=rst.getInt(3);
    					}
    					conn.close();
    				}
    			}
    		}
    		catch(Exception e)
    		{
    			e.printStackTrace();
    		}
    	}

    	public String getFoo() { return foo; }

    	public int getBar() { return bar;}
    }

### Data Sources and JNDI

All the `ConnectionPoolDataSource` and `DataSource` implementations can be stored in JNDI. In the case of the nonpooling implementations, a new instance will be created every time the object is retrieved from JNDI, with the same settings as the instance that was stored. For the pooling implementations, the same instance will be retrieved as long as it is available (e.g., not a different JVM retrieving the pool from JNDI), or a new instance with the same settings created otherwise.

In the application server environment, typically the application server's `DataSource` instance will be stored in JNDI, instead of the PostgreSQL `ConnectionPoolDataSource` implementation.

In an application environment, the application may store the `DataSource` in JNDI so that it doesn't have to make a reference to the `DataSource` available to all application components that may need to use it. An example of this is shown in ds-jndi.

#### `DataSource` JNDI Code Example

Application code to initialize a pooling `DataSource` and add it to JNDI might look like this:

    PGPoolingDataSource source = new PGPoolingDataSource();
    source.setDataSourceName("A Data Source");
    source.setServerName("localhost");
    source.setDatabaseName("test");
    source.setUser("testuser");
    source.setPassword("testpassword");
    source.setMaxConnections(10);
    new InitialContext().rebind("DataSource", source);

Then code to use a connection from the pool might look like this:

    Connection conn = null;
    try {
        DataSource source = (DataSource)new InitialContext().lookup("DataSource");
        conn = source.getConnection();
        // use connection
    } catch (SQLException e) {
        // log error
    } catch (NamingException e) {
        // DataSource wasn't found in JNDI
    } finally {
        if (con != null) {
            try { conn.close(); } catch (SQLException e) {}
        }
    }

## Further Reading

If you have not yet read it, you are advised you read the JDBC API Documentation (supplied with Sun's JDK) and the JDBC Specification. Both are available from .

contains updated information not included in this manual including Javadoc class documentation and a FAQ. Additionally it offers precompiled drivers.