Turso Database is currently in BETA. It may contain bugs and unexpected behavior. Use caution with production data and ensure you have backups.
Turso provides a JDBC driver that integrates with standard Java java.sql interfaces. You can use it anywhere a JDBC driver is accepted.
The Java binding is not yet published to Maven Central. You must build the JAR locally and publish it to your local Maven repository before use. See the build instructions below.
Building locally
The driver must be built from source and published to your local Maven repository.
Clone the repository
git clone https://github.com/tursodatabase/turso
cd turso/bindings/java
Build the native library
Select the target that matches your platform: # macOS Apple Silicon
make macos_arm64
# macOS Intel
make macos_x86
# Linux x86-64
make linux_x86
# Windows
make windows
Installation
After publishing locally, add the dependency to your build file.
Gradle (Kotlin)
Gradle (Groovy)
Maven
repositories {
mavenLocal ()
}
dependencies {
implementation ( "tech.turso:turso:0.0.1-SNAPSHOT" )
}
repositories {
mavenLocal()
}
dependencies {
implementation 'tech.turso:turso:0.0.1-SNAPSHOT'
}
< dependency >
< groupId > tech.turso </ groupId >
< artifactId > turso </ artifactId >
< version > 0.0.1-SNAPSHOT </ version >
</ dependency >
Group ID: tech.turso — Artifact ID: turso
Connecting to a database
The Turso JDBC driver registers itself automatically when the class is loaded. Use DriverManager.getConnection() with a URL of the form jdbc:turso:<path>.
file-based database
in-memory database
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso:sample.db" )) {
// conn is ready to use
}
}
}
The JDBC URL prefix is jdbc:turso:. Everything after the prefix is treated as the database file path. Use ":memory:" for an in-memory database.
Executing queries
Create a Statement from the connection and call execute(), executeUpdate(), or executeQuery().
import java.sql. * ;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso:sample.db" )) {
try ( Statement stmt = conn . createStatement (
ResultSet . TYPE_FORWARD_ONLY ,
ResultSet . CONCUR_READ_ONLY ,
ResultSet . CLOSE_CURSORS_AT_COMMIT )) {
// DDL
stmt . execute ( "CREATE TABLE users (id INT PRIMARY KEY, username TEXT)" );
// DML
stmt . execute ( "INSERT INTO users VALUES (1, 'alice')" );
stmt . execute ( "INSERT INTO users VALUES (2, 'bob')" );
// Query
stmt . execute ( "SELECT * FROM users" );
ResultSet rs = stmt . getResultSet ();
while ( rs . next ()) {
System . out . println (
"id=" + rs . getInt ( 1 ) + ", username=" + rs . getString ( 2 )
);
}
}
}
}
}
Prepared statements
Use Connection.prepareStatement() to compile a SQL string with ? placeholders and execute it multiple times with different parameters.
import java.sql. * ;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso::memory:" )) {
try ( Statement stmt = conn . createStatement ()) {
stmt . execute ( "CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, price REAL)" );
}
String sql = "INSERT INTO products (name, price) VALUES (?, ?)" ;
try ( PreparedStatement pstmt = conn . prepareStatement (sql)) {
pstmt . setString ( 1 , "Widget" );
pstmt . setDouble ( 2 , 9.99 );
pstmt . executeUpdate ();
pstmt . setString ( 1 , "Gadget" );
pstmt . setDouble ( 2 , 19.99 );
pstmt . executeUpdate ();
}
String query = "SELECT * FROM products WHERE price < ?" ;
try ( PreparedStatement pstmt = conn . prepareStatement (query)) {
pstmt . setDouble ( 1 , 15.0 );
try ( ResultSet rs = pstmt . executeQuery ()) {
while ( rs . next ()) {
System . out . println ( rs . getString ( "name" ) + " — $" + rs . getDouble ( "price" ));
}
}
}
}
}
}
Parameter binding
PreparedStatement setter methods map Java types to SQL types:
Method SQL type setInt(index, value)INTEGER setLong(index, value)INTEGER setDouble(index, value)REAL setString(index, value)TEXT setBytes(index, value)BLOB setNull(index, sqlType)NULL
Parameter indexes are 1-based.
Reading results
Use a ResultSet to iterate over query results. Columns can be accessed by index (1-based) or by name.
import java.sql. * ;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso::memory:" )) {
try ( Statement stmt = conn . createStatement ()) {
stmt . execute ( "CREATE TABLE logs (id INTEGER, msg TEXT)" );
stmt . execute ( "INSERT INTO logs VALUES (1, 'start'), (2, 'stop')" );
}
try ( Statement stmt = conn . createStatement ();
ResultSet rs = stmt . executeQuery ( "SELECT id, msg FROM logs ORDER BY id" )) {
// Inspect column metadata
ResultSetMetaData meta = rs . getMetaData ();
System . out . println ( "Columns: " + meta . getColumnCount ());
for ( int i = 1 ; i <= meta . getColumnCount (); i ++ ) {
System . out . println ( " " + meta . getColumnName (i) + " (" + meta . getColumnTypeName (i) + ")" );
}
while ( rs . next ()) {
// Access by index (1-based)
int id = rs . getInt ( 1 );
// Access by name
String msg = rs . getString ( "msg" );
System . out . println (id + ": " + msg);
}
}
}
}
}
Transactions
Disable auto-commit to group statements into a transaction. Call commit() to persist or rollback() to abort.
import java.sql. * ;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso::memory:" )) {
try ( Statement stmt = conn . createStatement ()) {
stmt . execute ( "CREATE TABLE accounts (id INTEGER PRIMARY KEY, balance INTEGER)" );
stmt . execute ( "INSERT INTO accounts VALUES (1, 1000), (2, 500)" );
}
conn . setAutoCommit ( false );
try {
try ( PreparedStatement debit = conn . prepareStatement (
"UPDATE accounts SET balance = balance - ? WHERE id = ?" );
PreparedStatement credit = conn . prepareStatement (
"UPDATE accounts SET balance = balance + ? WHERE id = ?" )) {
debit . setInt ( 1 , 100 );
debit . setInt ( 2 , 1 );
debit . executeUpdate ();
credit . setInt ( 1 , 100 );
credit . setInt ( 2 , 2 );
credit . executeUpdate ();
}
conn . commit ();
System . out . println ( "Transfer complete" );
} catch ( SQLException e ) {
conn . rollback ();
System . err . println ( "Transfer failed: " + e . getMessage ());
} finally {
conn . setAutoCommit ( true );
}
}
}
}
Error handling
The driver throws java.sql.SQLException on all database errors. Use the standard JDBC exception handling pattern:
try {
stmt . execute ( "INSERT INTO users VALUES (1, 'duplicate')" );
} catch ( SQLException e ) {
System . err . println ( "SQL error: " + e . getMessage ());
System . err . println ( "Error code: " + e . getErrorCode ());
System . err . println ( "SQL state: " + e . getSQLState ());
}
Complete example
import java.sql. * ;
public class Example {
public static void main ( String [] args ) throws SQLException {
try ( Connection conn = DriverManager . getConnection ( "jdbc:turso:sample.db" )) {
// Create table
try ( Statement stmt = conn . createStatement (
ResultSet . TYPE_FORWARD_ONLY ,
ResultSet . CONCUR_READ_ONLY ,
ResultSet . CLOSE_CURSORS_AT_COMMIT )) {
stmt . execute (
"CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY, username TEXT)"
);
}
// Insert with prepared statement
try ( PreparedStatement insert = conn . prepareStatement (
"INSERT INTO users VALUES (?, ?)" )) {
insert . setInt ( 1 , 1 );
insert . setString ( 2 , "alice" );
insert . executeUpdate ();
insert . setInt ( 1 , 2 );
insert . setString ( 2 , "bob" );
insert . executeUpdate ();
}
// Query
try ( Statement stmt = conn . createStatement (
ResultSet . TYPE_FORWARD_ONLY ,
ResultSet . CONCUR_READ_ONLY ,
ResultSet . CLOSE_CURSORS_AT_COMMIT )) {
stmt . execute ( "SELECT * FROM users" );
ResultSet rs = stmt . getResultSet ();
System . out . println (
rs . getInt ( 1 ) + ", " + rs . getString ( 2 )
);
}
}
}
}