JDBC
Integration
Selekt requires Java 25 or later.
Gradle
repositories {
mavenCentral()
}
dependencies {
implementation(platform("com.bloomberg.selekt:selekt-bom:0.33.2"))
implementation("com.bloomberg.selekt:selekt-jdbc")
}
repositories {
mavenCentral()
}
dependencies {
implementation platform('com.bloomberg.selekt:selekt-bom:0.33.2')
implementation 'com.bloomberg.selekt:selekt-jdbc'
}
Maven
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bloomberg.selekt</groupId>
<artifactId>selekt-bom</artifactId>
<version>0.33.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.bloomberg.selekt</groupId>
<artifactId>selekt-jdbc</artifactId>
</dependency>
</dependencies>
Getting a connection
Using a DataSource
val dataSource = SelektDataSource().apply {
databasePath = "/path/to/database.db"
journalMode = "WAL" // is the default journal mode
busyTimeout = 2_500 // milliseconds is the default busy timeout
maxPoolSize = 4 // is the default, 3 read-only connections
foreignKeys = true
}
dataSource.connection.use { connection ->
// Use connection
}
final SelektDataSource dataSource = new SelektDataSource();
dataSource.setDatabasePath("/path/to/database.db");
dataSource.setJournalMode("WAL"); // is the default journal mode
dataSource.setBusyTimeout(2500); // milliseconds is the default busy timeout
dataSource.setMaxPoolSize(4); // is the default, 3 read-only connections
dataSource.setForeignKeys(true);
try (Connection connection = dataSource.getConnection()) {
// Use connection
}
Using DriverManager
val url = "jdbc:sqlite:/path/to/database.db"
val connection = DriverManager.getConnection(url)
final String url = "jdbc:sqlite:/path/to/database.db";
final Connection connection = DriverManager.getConnection(url);
Connection properties can be passed via the URL query string or a Properties object:
val url = "jdbc:sqlite:/path/to/database.db" +
"?journalMode=WAL&busyTimeout=2500&poolSize=4&foreignKeys=true"
val connection = DriverManager.getConnection(url)
final Properties properties = new Properties();
properties.setProperty("journalMode", "WAL");
properties.setProperty("busyTimeout", "2500");
properties.setProperty("poolSize", "4");
properties.setProperty("foreignKeys", "true");
final Connection connection = DriverManager.getConnection(
"jdbc:sqlite:/path/to/database.db",
properties
);
Encryption
Selekt uses SQLCipher for AES-256 encryption. Encryption is opt-in, databases are unencrypted by default. To enable encryption, provide a key that is exactly 32 bytes.
With a DataSource
private fun deriveKey(): CharArray = TODO(
"Derive a 32-byte encryption key.")
val dataSource = SelektDataSource().apply {
databasePath = "/path/to/encrypted.db"
setEncryption(EncryptionKeySource.Literal(deriveKey()))
}
private char[] deriveKey() {
// TODO Derive a 32-byte encryption key.
}
final SelektDataSource dataSource = new SelektDataSource();
dataSource.setDatabasePath("/path/to/encrypted.db");
dataSource.setEncryption(
new EncryptionKeySource.Literal(deriveKey()));
With a hex key
val key = "0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
dataSource.setEncryption(
EncryptionKeySource.Literal(key.toCharArray())
)
final String key =
"0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
dataSource.setEncryption(
new EncryptionKeySource.Literal(key.toCharArray()));
Interaction
Querying with a PreparedStatement
dataSource.connection.use { connection ->
connection.prepareStatement(
"SELECT id, name FROM users WHERE id = ?"
).use { statement ->
statement.setInt(1, 42)
statement.executeQuery().use { resultSet ->
while (resultSet.next()) {
println(
"${resultSet.getInt("id")}: ${resultSet.getString("name")}"
)
}
}
}
}
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(
"SELECT id, name FROM users WHERE id = ?")) {
statement.setInt(1, 42);
try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
System.out.println(
resultSet.getInt("id") + ": " + resultSet.getString("name")
);
}
}
}
Inserting data
dataSource.connection.use { connection ->
connection.prepareStatement(
"INSERT INTO users (id, name) VALUES (?, ?)"
).use { statement ->
statement.setInt(1, 1)
statement.setString(2, "Alice")
statement.executeUpdate()
}
}
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(
"INSERT INTO users (id, name) VALUES (?, ?)")) {
statement.setInt(1, 1);
statement.setString(2, "Alice");
statement.executeUpdate();
}
Batch inserts
dataSource.connection.use { connection ->
connection.autoCommit = false
try {
connection.prepareStatement(
"INSERT INTO users (id, name) VALUES (?, ?)"
).use { statement ->
for (i in 1..1000) {
statement.setInt(1, i)
statement.setString(2, "User $i")
statement.addBatch()
}
statement.executeBatch()
}
connection.commit()
} catch (e: SQLException) {
connection.rollback()
throw e
}
}
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(
"INSERT INTO users (id, name) VALUES (?, ?)"
)) {
for (int i = 1; i <= 1000; i++) {
statement.setInt(1, i);
statement.setString(2, "User " + i);
statement.addBatch();
}
statement.executeBatch();
connection.commit();
} catch (final SQLException e) {
connection.rollback();
throw e;
}
}
Transactions
dataSource.connection.use { connection ->
connection.autoCommit = false
try {
connection.prepareStatement(
"UPDATE accounts SET balance = balance - ? WHERE id = ?"
).use { statement ->
statement.setDouble(1, 100.0)
statement.setInt(2, 1)
statement.executeUpdate()
}
connection.prepareStatement(
"UPDATE accounts SET balance = balance + ? WHERE id = ?"
).use { statement ->
statement.setDouble(1, 100.0)
statement.setInt(2, 2)
statement.executeUpdate()
}
connection.commit()
} catch (e: SQLException) {
connection.rollback()
throw e
}
}
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try {
try (final PreparedStatement statement = connection.prepareStatement(
"UPDATE accounts SET balance = balance - ? WHERE id = ?"
)) {
statement.setDouble(1, 100.0);
statement.setInt(2, 1);
statement.executeUpdate();
}
try (final PreparedStatement statement = connection.prepareStatement(
"UPDATE accounts SET balance = balance + ? WHERE id = ?"
)) {
statement.setDouble(1, 100.0);
statement.setInt(2, 2);
statement.executeUpdate();
}
connection.commit();
} catch (final SQLException e) {
connection.rollback();
throw e;
}
}
Connection properties
| Property | Type | Default | Description |
|---|---|---|---|
journalMode |
String | WAL |
SQLite journal mode (DELETE, TRUNCATE, PERSIST, MEMORY, WAL, OFF) |
busyTimeout |
int | 2500 |
SQLite busy timeout in milliseconds |
poolSize |
int | 4 |
Maximum connection pool size |
foreignKeys |
boolean | true |
Enable foreign key constraints |
key |
String | null |
Encryption key (hex string, via DriverManager only) |
Closing the DataSource
dataSource.close()
dataSource.close();
Calling close() releases all pooled connections and zeroes any encryption key material. The method is idempotent.