PostgreSQL JDBC Driver allows Java programs to connect to a PostgreSQL database using standard, database independent Java code.
This document covers the DataSource implementations provided by the PostgreSQL JDBC driver, including simple DataSource, connection pooling DataSource, and XA-enabled DataSource for distributed transactions.
All PostgreSQL DataSource implementations extend from a common base class org.postgresql.ds.common.BaseDataSource which provides shared configuration properties and connection setup logic.
Inheritance Hierarchy:
BaseDataSource (abstract)
├── PGSimpleDataSource - Simple non-pooling DataSource
├── PGConnectionPoolDataSource - For use with connection pool managers
└── PGXADataSource - XA-enabled for distributed transactionsAll three implementations inherit the same configuration methods from BaseDataSource:
setServerName, setPortNumber, setDatabaseName)setUser, setPassword)setSsl, setSslMode, setSslFactory, etc.)setLoginTimeout, setConnectTimeout, setSocketTimeout)setPrepareThreshold, setDefaultRowFetchSize, setBinaryTransfer, etc.)setApplicationName, setAutosave, setPreferQueryMode, etc.)The only differences between the three DataSource types are:
Connection vs PooledConnection vs XAConnection)Non-pooling DataSource implementation suitable for simple applications or when using external connection pooling.
package org.postgresql.ds;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Simple non-pooling DataSource implementation.
* Creates a new physical connection for each getConnection() call.
* Suitable for applications with infrequent database access or
* when using external connection pooling (HikariCP, Apache DBCP, etc.).
*/
public class PGSimpleDataSource implements DataSource, Serializable {
/**
* Gets a connection using the configured properties.
*
* @return New database connection
* @throws SQLException if connection cannot be established
*/
public Connection getConnection() throws SQLException;
/**
* Gets a connection with specific credentials.
*
* @param user Database username
* @param password Database password
* @return New database connection
* @throws SQLException if connection cannot be established
*/
public Connection getConnection(String user, String password) throws SQLException;
/**
* Gets a description of this DataSource.
*
* @return Description string
*/
public String getDescription();
// Configuration methods
/**
* Sets the PostgreSQL server hostname.
*
* @param serverName Hostname or IP address (default: localhost)
*/
public void setServerName(String serverName);
/**
* Gets the PostgreSQL server hostname.
*/
public String getServerName();
/**
* Sets the PostgreSQL server port number.
*
* @param portNumber Port number (default: 5432)
*/
public void setPortNumber(int portNumber);
/**
* Gets the PostgreSQL server port number.
*/
public int getPortNumber();
/**
* Sets the database name.
*
* @param databaseName Database name to connect to
*/
public void setDatabaseName(String databaseName);
/**
* Gets the database name.
*/
public String getDatabaseName();
/**
* Sets the database user.
*
* @param user Username for authentication
*/
public void setUser(String user);
/**
* Gets the database user.
*/
public String getUser();
/**
* Sets the database password.
*
* @param password Password for authentication
*/
public void setPassword(String password);
/**
* Gets the database password.
*/
public String getPassword();
// Additional property setters/getters
/**
* Sets the application name for connection tracking.
*/
public void setApplicationName(String applicationName);
public String getApplicationName();
/**
* Enables or disables SSL.
*/
public void setSsl(boolean ssl);
public boolean getSsl();
/**
* Sets the SSL mode.
*
* @param sslMode One of: disable, allow, prefer, require, verify-ca, verify-full
*/
public void setSslMode(String sslMode);
public String getSslMode();
/**
* Sets the SSL factory class name.
*/
public void setSslFactory(String sslFactory);
public String getSslFactory();
/**
* Sets the connection timeout in seconds.
*/
public void setConnectTimeout(int connectTimeout);
public int getConnectTimeout();
/**
* Sets the socket timeout in seconds.
*/
public void setSocketTimeout(int socketTimeout);
public int getSocketTimeout();
/**
* Sets the login timeout in seconds.
*/
public void setLoginTimeout(int loginTimeout);
public int getLoginTimeout();
/**
* Sets the prepare threshold.
*/
public void setPrepareThreshold(int prepareThreshold);
public int getPrepareThreshold();
/**
* Sets the default fetch size.
*/
public void setDefaultRowFetchSize(int defaultRowFetchSize);
public int getDefaultRowFetchSize();
/**
* Enables or disables binary transfer.
*/
public void setBinaryTransfer(boolean binaryTransfer);
public boolean getBinaryTransfer();
/**
* Sets the replication mode.
*
* @param replication "database" or "true" to enable replication protocol
*/
public void setReplication(String replication);
public String getReplication();
/**
* Sets the autosave mode.
*
* @param autosave One of: never, always, conservative
*/
public void setAutosave(String autosave);
public String getAutosave();
/**
* Sets the preferred query mode.
*
* @param preferQueryMode One of: simple, extended, extendedForPrepared,
* extendedCacheEverything
*/
public void setPreferQueryMode(String preferQueryMode);
public String getPreferQueryMode();
/**
* Sets the target server type for multi-host connections.
*
* @param targetServerType One of: any, primary, secondary, preferSecondary
*/
public void setTargetServerType(String targetServerType);
public String getTargetServerType();
/**
* Enables or disables load balancing across hosts.
*/
public void setLoadBalanceHosts(boolean loadBalanceHosts);
public boolean getLoadBalanceHosts();
/**
* Sets multiple server names for failover.
*
* @param serverNames Comma-separated list of hostnames
*/
public void setServerNames(String[] serverNames);
public String[] getServerNames();
/**
* Sets multiple port numbers corresponding to server names.
*
* @param portNumbers Array of port numbers
*/
public void setPortNumbers(int[] portNumbers);
public int[] getPortNumbers();
}Usage Examples:
import org.postgresql.ds.PGSimpleDataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
// Example 1: Basic DataSource configuration
public class SimpleDataSourceExample {
public static void main(String[] args) throws SQLException {
// Create and configure DataSource
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setServerName("localhost");
ds.setPortNumber(5432);
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
// Get connection and use it
try (Connection conn = ds.getConnection()) {
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT version()")) {
if (rs.next()) {
System.out.println("PostgreSQL version: " + rs.getString(1));
}
}
}
}
}
// Example 2: DataSource with SSL
public class SecureDataSource {
public static PGSimpleDataSource createSecureDataSource() {
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setServerName("secure-db.example.com");
ds.setPortNumber(5432);
ds.setDatabaseName("production");
ds.setUser("app_user");
ds.setPassword("strong_password");
// Enable SSL with certificate verification
ds.setSsl(true);
ds.setSslMode("verify-full");
ds.setSslFactory("org.postgresql.ssl.LibPQFactory");
// Set timeouts
ds.setConnectTimeout(10);
ds.setSocketTimeout(30);
// Set application name for tracking
ds.setApplicationName("MyApp");
return ds;
}
}
// Example 3: DataSource with performance tuning
public class TunedDataSource {
public static PGSimpleDataSource createTunedDataSource() {
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setServerName("localhost");
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
// Performance settings
ds.setPrepareThreshold(5); // Prepare statements after 5 executions
ds.setDefaultRowFetchSize(100); // Fetch 100 rows at a time
ds.setBinaryTransfer(true); // Use binary protocol
ds.setPreferQueryMode("extendedForPrepared");
// Autosave for better error recovery
ds.setAutosave("conservative");
return ds;
}
}
// Example 4: Multi-host DataSource for high availability
public class HADataSource {
public static PGSimpleDataSource createHADataSource() {
PGSimpleDataSource ds = new PGSimpleDataSource();
// Configure multiple hosts
ds.setServerNames(new String[]{"db1.example.com", "db2.example.com", "db3.example.com"});
ds.setPortNumbers(new int[]{5432, 5432, 5432});
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
// Target primary server only
ds.setTargetServerType("primary");
// Enable load balancing for read replicas
// ds.setTargetServerType("secondary");
// ds.setLoadBalanceHosts(true);
return ds;
}
}
// Example 5: Programmatic property configuration
public class DynamicDataSource {
public static PGSimpleDataSource createFromProperties(
String host, int port, String database,
String user, String password,
boolean useSSL) {
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setServerName(host);
ds.setPortNumber(port);
ds.setDatabaseName(database);
ds.setUser(user);
ds.setPassword(password);
if (useSSL) {
ds.setSsl(true);
ds.setSslMode("require");
}
return ds;
}
}DataSource implementation for use with external connection pool managers (e.g., Java EE application servers).
package org.postgresql.ds;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.io.Serializable;
import java.sql.SQLException;
/**
* ConnectionPoolDataSource implementation for connection pooling.
* Designed to work with external connection pool managers.
* Applications should use a connection pooling framework rather than
* using this class directly.
*/
public class PGConnectionPoolDataSource implements ConnectionPoolDataSource, Serializable {
/**
* Gets a physical database connection that can be used for connection pooling.
*
* @return PooledConnection that wraps a physical connection
* @throws SQLException if connection cannot be established
*/
public PooledConnection getPooledConnection() throws SQLException;
/**
* Gets a pooled connection with specific credentials.
*
* @param user Database username
* @param password Database password
* @return PooledConnection that wraps a physical connection
* @throws SQLException if connection cannot be established
*/
public PooledConnection getPooledConnection(String user, String password)
throws SQLException;
/**
* Gets a description of this DataSource.
*
* @return Description string
*/
public String getDescription();
/**
* Gets whether connections supplied by this pool will have autoCommit enabled by default.
*
* @return true if connections will have autoCommit enabled by default
*/
public boolean isDefaultAutoCommit();
/**
* Sets whether connections supplied by this pool will have autoCommit enabled by default.
* If not set, connections will use the JDBC driver's default behavior.
*
* @param defaultAutoCommit true to enable autoCommit by default, false to disable
*/
public void setDefaultAutoCommit(boolean defaultAutoCommit);
// Inherits all configuration methods from BaseDataSource
// Same setters/getters as PGSimpleDataSource:
// - setServerName/getServerName
// - setPortNumber/getPortNumber
// - setDatabaseName/getDatabaseName
// - setUser/getUser
// - setPassword/getPassword
// - etc.
}Usage Examples:
import org.postgresql.ds.PGConnectionPoolDataSource;
import javax.sql.PooledConnection;
import java.sql.Connection;
import java.sql.SQLException;
// Example 1: Basic pooled connection
public class PooledConnectionExample {
public static void usePooledConnection() throws SQLException {
// Configure DataSource
PGConnectionPoolDataSource ds = new PGConnectionPoolDataSource();
ds.setServerName("localhost");
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
// Get pooled connection
PooledConnection pooledConn = ds.getPooledConnection();
// Get logical connection from pooled connection
Connection conn = pooledConn.getConnection();
// Use connection...
// When conn.close() is called, the logical connection is closed
// but the physical connection remains open in the pool
conn.close();
// Can get another logical connection from same pooled connection
Connection conn2 = pooledConn.getConnection();
conn2.close();
// Close physical connection
pooledConn.close();
}
}
// Example 2: With connection event listener
public class ConnectionEventExample {
public static void setupWithListener() throws SQLException {
PGConnectionPoolDataSource ds = new PGConnectionPoolDataSource();
ds.setServerName("localhost");
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
PooledConnection pooledConn = ds.getPooledConnection();
// Add listener for connection events
pooledConn.addConnectionEventListener(new ConnectionEventListener() {
@Override
public void connectionClosed(ConnectionEvent event) {
System.out.println("Logical connection closed");
}
@Override
public void connectionErrorOccurred(ConnectionEvent event) {
System.out.println("Connection error: " + event.getSQLException());
}
});
Connection conn = pooledConn.getConnection();
// Use connection...
conn.close(); // Triggers connectionClosed event
pooledConn.close();
}
}
// Example 3: Integration with pooling framework (conceptual)
public class PoolingFrameworkIntegration {
// This is typically done by the pooling framework, not application code
public static void setupPool() {
PGConnectionPoolDataSource ds = new PGConnectionPoolDataSource();
ds.setServerName("localhost");
ds.setDatabaseName("mydb");
ds.setUser("postgres");
ds.setPassword("secret");
// Connection pooling framework (e.g., HikariCP, Apache DBCP)
// would use this DataSource to create pooled connections
// Application code would then request connections from the pool
}
}XA-enabled DataSource for distributed transactions across multiple resources.
package org.postgresql.xa;
import javax.sql.XADataSource;
import javax.sql.XAConnection;
import java.io.Serializable;
import java.sql.SQLException;
/**
* XA-enabled DataSource for distributed (two-phase commit) transactions.
* Implements the Java Transaction API (JTA) XADataSource interface.
* Used with transaction managers in Java EE or standalone JTA environments.
*/
public class PGXADataSource implements XADataSource, Serializable {
/**
* Gets an XA connection for distributed transactions.
*
* @return XAConnection that supports two-phase commit
* @throws SQLException if connection cannot be established
*/
public XAConnection getXAConnection() throws SQLException;
/**
* Gets an XA connection with specific credentials.
*
* @param user Database username
* @param password Database password
* @return XAConnection that supports two-phase commit
* @throws SQLException if connection cannot be established
*/
public XAConnection getXAConnection(String user, String password)
throws SQLException;
/**
* Gets a description of this DataSource.
*
* @return Description string
*/
public String getDescription();
// Inherits all configuration methods from BaseDataSource
// Same setters/getters as PGSimpleDataSource
}Related XA Interfaces:
package org.postgresql.xa;
import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.Connection;
import java.sql.SQLException;
/**
* PostgreSQL implementation of XAConnection.
* Combines pooled connection functionality with XA resource management.
*/
public class PGXAConnection implements XAConnection, XAResource {
/**
* Gets the XAResource for transaction management.
*
* @return XAResource instance
* @throws SQLException if resource cannot be obtained
*/
public XAResource getXAResource() throws SQLException;
/**
* Gets a logical connection handle.
*
* @return Connection for database operations
* @throws SQLException if connection cannot be obtained
*/
public Connection getConnection() throws SQLException;
/**
* Closes the physical connection.
*
* @throws SQLException if close fails
*/
public void close() throws SQLException;
// XAResource methods for two-phase commit protocol
/**
* Starts work on behalf of a transaction branch.
*
* @param xid Transaction branch identifier
* @param flags TMNOFLAGS, TMJOIN, or TMRESUME
* @throws XAException if operation fails
*/
public void start(Xid xid, int flags) throws XAException;
/**
* Ends work on behalf of a transaction branch.
*
* @param xid Transaction branch identifier
* @param flags TMSUCCESS, TMFAIL, or TMSUSPEND
* @throws XAException if operation fails
*/
public void end(Xid xid, int flags) throws XAException;
/**
* Prepares the transaction branch for commit (phase 1).
*
* @param xid Transaction branch identifier
* @return XA_OK or XA_RDONLY
* @throws XAException if prepare fails
*/
public int prepare(Xid xid) throws XAException;
/**
* Commits the transaction branch (phase 2).
*
* @param xid Transaction branch identifier
* @param onePhase If true, one-phase commit optimization
* @throws XAException if commit fails
*/
public void commit(Xid xid, boolean onePhase) throws XAException;
/**
* Rolls back the transaction branch.
*
* @param xid Transaction branch identifier
* @throws XAException if rollback fails
*/
public void rollback(Xid xid) throws XAException;
/**
* Recovers prepared transactions (for crash recovery).
*
* @param flag TMSTARTRSCAN, TMENDRSCAN, or TMNOFLAGS
* @return Array of transaction branch identifiers
* @throws XAException if recovery fails
*/
public Xid[] recover(int flag) throws XAException;
/**
* Forgets about a heuristically completed transaction branch.
*
* @param xid Transaction branch identifier
* @throws XAException if forget fails
*/
public void forget(Xid xid) throws XAException;
/**
* Checks if this resource manager is the same as another.
*
* @param xares Another XAResource
* @return true if same resource manager
* @throws XAException if check fails
*/
public boolean isSameRM(XAResource xares) throws XAException;
/**
* Sets the transaction timeout.
*
* @param seconds Timeout in seconds
* @return true if timeout was set
* @throws XAException if operation fails
*/
public boolean setTransactionTimeout(int seconds) throws XAException;
/**
* Gets the transaction timeout.
*
* @return Timeout in seconds
* @throws XAException if operation fails
*/
public int getTransactionTimeout() throws XAException;
}Usage Examples:
import org.postgresql.xa.PGXADataSource;
import javax.sql.XAConnection;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
// Example 1: Basic XA connection
public class XAConnectionExample {
public static void useXAConnection() throws SQLException {
// Configure XA DataSource
PGXADataSource xads = new PGXADataSource();
xads.setServerName("localhost");
xads.setDatabaseName("mydb");
xads.setUser("postgres");
xads.setPassword("secret");
// Get XA connection
XAConnection xaConn = xads.getXAConnection();
// Get XA resource for transaction management
XAResource xaRes = xaConn.getXAResource();
// Get regular connection for database operations
Connection conn = xaConn.getConnection();
// Use connection...
conn.close();
xaConn.close();
}
}
// Example 2: Distributed transaction (simplified)
public class DistributedTransactionExample {
// This is a simplified example. In practice, use a JTA transaction manager.
public static void distributedTransaction() throws Exception {
// Setup two XA DataSources
PGXADataSource xads1 = new PGXADataSource();
xads1.setServerName("db1.example.com");
xads1.setDatabaseName("db1");
xads1.setUser("user1");
xads1.setPassword("pass1");
PGXADataSource xads2 = new PGXADataSource();
xads2.setServerName("db2.example.com");
xads2.setDatabaseName("db2");
xads2.setUser("user2");
xads2.setPassword("pass2");
// Get XA connections and resources
XAConnection xaConn1 = xads1.getXAConnection();
XAConnection xaConn2 = xads2.getXAConnection();
XAResource xaRes1 = xaConn1.getXAResource();
XAResource xaRes2 = xaConn2.getXAResource();
Connection conn1 = xaConn1.getConnection();
Connection conn2 = xaConn2.getConnection();
// Create transaction IDs
Xid xid1 = createXid(1);
Xid xid2 = createXid(2);
try {
// Start transaction branches
xaRes1.start(xid1, XAResource.TMNOFLAGS);
xaRes2.start(xid2, XAResource.TMNOFLAGS);
// Do work on both databases
try (Statement stmt1 = conn1.createStatement()) {
stmt1.executeUpdate("INSERT INTO accounts (id, balance) VALUES (1, 100)");
}
try (Statement stmt2 = conn2.createStatement()) {
stmt2.executeUpdate("INSERT INTO ledger (account_id, amount) VALUES (1, 100)");
}
// End transaction branches
xaRes1.end(xid1, XAResource.TMSUCCESS);
xaRes2.end(xid2, XAResource.TMSUCCESS);
// Prepare (phase 1)
int prepare1 = xaRes1.prepare(xid1);
int prepare2 = xaRes2.prepare(xid2);
// Commit (phase 2)
if (prepare1 == XAResource.XA_OK) {
xaRes1.commit(xid1, false);
}
if (prepare2 == XAResource.XA_OK) {
xaRes2.commit(xid2, false);
}
} catch (Exception e) {
// Rollback on error
try {
xaRes1.rollback(xid1);
} catch (Exception ignored) {}
try {
xaRes2.rollback(xid2);
} catch (Exception ignored) {}
throw e;
} finally {
conn1.close();
conn2.close();
xaConn1.close();
xaConn2.close();
}
}
private static Xid createXid(int branchId) {
// Create a simple Xid implementation
return new Xid() {
@Override
public int getFormatId() { return 1; }
@Override
public byte[] getGlobalTransactionId() {
return ("gtxid-" + System.currentTimeMillis()).getBytes();
}
@Override
public byte[] getBranchQualifier() {
return ("branch-" + branchId).getBytes();
}
};
}
}
// Example 3: XA with JTA transaction manager (conceptual)
public class JTAIntegration {
// In a Java EE environment or with standalone JTA:
public static void useWithJTA() throws Exception {
// Configure XA DataSource
PGXADataSource xads = new PGXADataSource();
xads.setServerName("localhost");
xads.setDatabaseName("mydb");
xads.setUser("postgres");
xads.setPassword("secret");
// Register with JNDI (in Java EE)
// Context ctx = new InitialContext();
// ctx.bind("jdbc/PostgresXA", xads);
// Transaction manager handles XA protocol
// UserTransaction tx = ...
// tx.begin();
// Connection conn = xads.getXAConnection().getConnection();
// // do work
// tx.commit(); // Transaction manager coordinates 2PC
}
}When to use each DataSource:
| DataSource Type | Use Case | Connection Management | Transaction Support |
|---|---|---|---|
| PGSimpleDataSource | Simple apps, external pooling | Each getConnection() creates new physical connection | Local transactions only |
| PGConnectionPoolDataSource | Integration with connection pool managers | Physical connections managed by pool | Local transactions only |
| PGXADataSource | Distributed transactions | Physical connections managed by pool | Distributed (XA) transactions |
Best Practices:
PGSimpleDataSource with an external connection pool like HikariCPPGConnectionPoolDataSource or PGXADataSource with app server's poolingPGXADataSource with a JTA transaction managerPGPoolingDataSource (use external pooling instead)Connection Pool Configuration Example (HikariCP):
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.postgresql.ds.PGSimpleDataSource;
public class HikariCPExample {
public static HikariDataSource createPooledDataSource() {
// Create PostgreSQL DataSource
PGSimpleDataSource pgds = new PGSimpleDataSource();
pgds.setServerName("localhost");
pgds.setDatabaseName("mydb");
pgds.setUser("postgres");
pgds.setPassword("secret");
// Configure HikariCP
HikariConfig config = new HikariConfig();
config.setDataSource(pgds);
config.setMaximumPoolSize(10);
config.setMinimumIdle(2);
config.setConnectionTimeout(30000); // 30 seconds
config.setIdleTimeout(600000); // 10 minutes
config.setMaxLifetime(1800000); // 30 minutes
config.setPoolName("PostgreSQL-Pool");
// Validation
config.setConnectionTestQuery("SELECT 1");
config.setValidationTimeout(5000); // 5 seconds
return new HikariDataSource(config);
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-postgresql--postgresql