Skip to content

JDBC Driver

This page is the JDBC reference. For the higher-level Java SDK overview, see Java SDK.

Coordinatesai.particledb:particledb-jdbc:1.0.0
JDBC driver classorg.particledb.Driver
URL prefixjdbc:particledb://host:port/database
Default port5440 (PDB native wire) — 5443 for TLS
TransportPDB native wire v2 (HTTP/2-style multiplex over one TCP)
DependenciesNetty 4.1.115, Apache Arrow 15.0.2 (optional, required for SELECT)
LicenseApache-2.0
Min Java11 (DDL/DML); 17+ recommended for SELECT

Available on Maven Central — no extra <repository> declaration needed.

<dependencies>
<dependency>
<groupId>ai.particledb</groupId>
<artifactId>particledb-jdbc</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.arrow</groupId>
<artifactId>arrow-vector</artifactId>
<version>15.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.arrow</groupId>
<artifactId>arrow-memory-netty</artifactId>
<version>15.0.2</version>
</dependency>
</dependencies>

JVM flags (required for result-set decode)

Section titled “JVM flags (required for result-set decode)”

Arrow Java reflects into ByteBuffer internals; Netty also benefits from explicit reflection access. Add to your JVM startup arguments — or set in pom.xml/build.gradle for tests:

--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED
-Dio.netty.tryReflectionSetAccessible=true

The driver throws a clear, actionable error if the add-opens flags are missing when a SELECT result-set is decoded (it does NOT silently fall back to raw bytes). The Netty system property is recommended; the samples module sets it by default.

jdbc:particledb://host[:port][/database][?option=value&...]

User + password are passed as separate JDBC Properties (or via the PdbDataSource setters), not embedded in the URL. The parser does not support user:password@ userinfo today.

OptionDefaultDescription
prepareThreshold5Number of executions before promotion to a server-side prepared statement. Matches pgjdbc.
preparedStatementCacheQueries256Client-side prepared statement cache size (entries).
preparedStatementCacheSizeMiB5Client-side prepared statement cache cap (MiB).
maxStreamsPerConn64Wire-v2 multiplex stream cap per TCP connection.
preferUnixSockettrueTry /tmp/.s.PDB.<port> first when host is local.
connectTimeout30000TCP + handshake timeout, milliseconds.
sslModedisableTLS mode (see below).
sslRootCertPath to PEM CA bundle for verify-ca / verify-full.
sslCertPath to PEM client cert for mTLS.
sslKeyPath to PEM client private key for mTLS.
ModeEncrypts wire?Verifies CA chain?Verifies hostname?
disablenonono
requireyesnono
verify-cayesyesno
verify-fullyesyesyes

Use verify-full in production. The TLS port is 5443; port 5440 is plaintext PDB wire.

import java.sql.*;
public class Hello {
public static void main(String[] args) throws Exception {
Class.forName("org.particledb.Driver");
try (Connection c = DriverManager.getConnection(
"jdbc:particledb://127.0.0.1:5440/default");
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT 1")) {
while (rs.next()) System.out.println(rs.getInt(1));
}
}
}
import org.particledb.ds.PdbDataSource;
PdbDataSource ds = new PdbDataSource();
ds.setHost("db.internal.example.com");
ds.setPort(5443);
ds.setDatabase("postgres");
ds.setUser("app");
ds.setPassword(System.getenv("PDB_PASSWORD"));
ds.setSslMode("verify-full");
ds.setSslRootCert("/etc/ssl/internal-ca.crt");
try (Connection c = ds.getConnection()) {
// ...
}

PdbDataSource exposes Hikari-friendly bean setters for every option in the table above.

The driver does not ship a built-in pool. Use HikariCP:

HikariConfig cfg = new HikariConfig();
cfg.setJdbcUrl("jdbc:particledb://127.0.0.1:5440/default");
cfg.setMaximumPoolSize(10);
cfg.setMinimumIdle(1);
cfg.setConnectionTimeout(30_000);
cfg.setPoolName("pdb-app");
HikariDataSource ds = new HikariDataSource(cfg);

PDB wire v2 already multiplexes streams per TCP connection, so a small pool (≤10) is typically sufficient.

PDB native wire treats BEGIN/COMMIT/ROLLBACK as batch markers, not full ACID transaction brackets. This means:

  • Connection.setAutoCommit(false) + a series of writes + commit() works correctly — writes flush as a batch on commit().
  • Connection.rollback() after a flushed write does not undo it on PDB native wire.
  • SAVEPOINT and isolation-level pinning are not yet supported on PDB native wire.

If your app relies on rollback-after-write or savepoints, connect via the PostgreSQL wire (port 5432) using stock pgjdbc instead — see the PG wire page. That path supports the full pgjdbc feature set including server-side prepared statements, pipelined execution, and interactive transactions.

Each sample is a main class under sdk/java/jdbc/samples/:

SampleDemonstrates
HelloWorldSmallest round-trip: SELECT 1.
CrudRoundtripCREATE / INSERT / SELECT / UPDATE / DELETE.
TransactionDemosetAutoCommit(false) + RYOW within a batch.
HikariCpDemoHikariCP integration.
PgJdbcCompatPG-wire compatibility via stock pgjdbc.

Run any sample after booting a local ParticleDB:

Terminal window
particledb start --no-auth --txn-mode occ-v3 \
--pg-addr 127.0.0.1:5432 --pdb-port 5440
cd sdk/java/jdbc/samples
mvn exec:exec -Dexec.mainClass=ai.particledb.jdbc.samples.HelloWorld

Checksums and GPG signatures are published next to the JAR under the standard Maven Central layout:

https://repo1.maven.org/maven2/ai/particledb/particledb-jdbc/1.0.0/particledb-jdbc-1.0.0.jar.md5
https://repo1.maven.org/maven2/ai/particledb/particledb-jdbc/1.0.0/particledb-jdbc-1.0.0.jar.sha1
https://repo1.maven.org/maven2/ai/particledb/particledb-jdbc/1.0.0/particledb-jdbc-1.0.0.jar.asc
Terminal window
curl -L -o /tmp/particledb-jdbc-1.0.0.jar \
https://repo1.maven.org/maven2/ai/particledb/particledb-jdbc/1.0.0/particledb-jdbc-1.0.0.jar
EXPECTED=$(curl -sL https://repo1.maven.org/maven2/ai/particledb/particledb-jdbc/1.0.0/particledb-jdbc-1.0.0.jar.sha1)
ACTUAL=$(shasum -a 1 /tmp/particledb-jdbc-1.0.0.jar | awk '{print $1}')
[ "$EXPECTED" = "$ACTUAL" ] && echo OK || echo MISMATCH
ClassPurpose
org.particledb.DriverJDBC Driver. SPI-registered via META-INF/services/java.sql.Driver.
org.particledb.PdbConnectionJDBC Connection. Wraps a StreamMux so each statement runs on its own multiplexed stream.
org.particledb.PdbPreparedStatementJDBC PreparedStatement with client-side parameter substitution and prepared-cache analytics.
org.particledb.PdbResultSetJDBC ResultSet. Decodes Arrow IPC via the optional arrow-vector dependency.
org.particledb.wire.WireV2CodecNetty ByteToMessageDecoder for v1 (8-byte header) and v2 (11-byte header) frames.
org.particledb.wire.StreamMuxMultiplexed connection manager: one TCP socket, N concurrent streams.
org.particledb.wire.ConnPoolSmall pool of mux instances for high-fan-out scenarios.
org.particledb.ds.PdbDataSourcejavax.sql.DataSource impl with HikariCP-friendly bean setters.

The driver always starts in v1 framing, sends a v1-framed HELLO announcing both CAP_V1_LEGACY and CAP_V2_MUX, and the server picks:

  • v1 server: returns chosen_caps & 0x02 == 0. Driver stays in v1 single-stream mode (one outstanding request at a time).
  • v2 server: returns chosen_caps & 0x02 == 1. Driver switches to v2 framing (11-byte header) and opens up to maxStreamsPerConn in-flight streams on this TCP connection.

See PDB_WIRE_V2 architecture for the full v2 spec.

  • TLS sslMode=require / verify-ca / verify-full (handshake currently validated on the connect path; per-mode strictness landing in v1.1).
  • Server-side Parse/Bind/Execute split (once the v2 server exposes those opcodes).
  • Full Arrow IPC decoding without reflection.
  • JNDI registration for app-server deployments.
  • CallableStatement for stored procedures.