BasicUtils

DuckDB Java JDBC Tutorial: How to Use DuckDB in Java Applications

Updated: Jun 1, 2025

By: Joseph Horace

#DuckDB Java tutorial
#DuckDB JDBC
#DuckDB JDBC tutorial
#DuckDB in Java
#embedded analytics Java
#DuckDB Java examples
#DuckDBConnection
#DuckDBAppender
#Java Parquet database
#DuckDB SQL Java

Table of Contents

  1. What is DuckDB?
  2. How to Add DuckDB JDBC to Your Java Project
  3. Connecting to DuckDB from Java
  4. Create Tables and Query DuckDB in Java
  5. Fast Inserts with DuckDBAppender in Java
  6. Read and Write Parquet Files in DuckDB via Java
  7. Cleanup
  8. Conclusion

If you're looking for a fast, embedded OLAP database for Java, DuckDB is a perfect choice. This tutorial walks you through setting up DuckDB with Java via JDBC, performing queries, inserting data efficiently, and working with Parquet files.

What is DuckDB?

DuckDB is a high-performance, in-process SQL OLAP database that runs like SQLite but is optimized for analytical workloads. It's great for Java developers who want fast data analysis without managing a separate database server.

How to Add DuckDB JDBC to Your Java Project

Maven

<dependency>
    <groupId>org.duckdb</groupId>
    <artifactId>duckdb_jdbc</artifactId>
    <version>0.9.1</version> <!-- Use the latest version -->
</dependency>

Gradle

implementation 'org.duckdb:duckdb_jdbc:0.9.1'
Tip: Always check Maven Central for the latest version of the DuckDB JDBC driver.

Connecting to DuckDB from Java

You can create either an in-memory or persistent DuckDB database using standard JDBC:

import java.sql.Connection;
import java.sql.DriverManager;
import org.duckdb.DuckDBConnection;
// In-memory database
Connection rawConn = DriverManager.getConnection("jdbc:duckdb:");
DuckDBConnection dbConn = (DuckDBConnection) rawConn;
// Persistent database
Connection fileConn = DriverManager.getConnection("jdbc:duckdb:/data/analytics.db");

Create Tables and Query DuckDB in Java

Once connected, you can execute SQL just like with other databases:

import java.sql.Statement;
import java.sql.ResultSet;
Statement sql = dbConn.createStatement();
// Create a new table
sql.execute("CREATE TABLE books (title VARCHAR, price DOUBLE, stock INT)");
// Insert rows
sql.execute("INSERT INTO books VALUES ('Java Basics', 29.99, 100), ('DuckDB Guide', 19.99, 50)");
// Query data
ResultSet results = sql.executeQuery("SELECT * FROM books");
while (results.next()) {
    System.out.printf("%s | $%.2f | Stock: %d%n",
        results.getString("title"),
        results.getDouble("price"),
        results.getInt("stock")
    );
}

Fast Inserts with DuckDBAppender in Java

For high-performance inserts (e.g., when importing a dataset), use the native DuckDBAppender:

import org.duckdb.DuckDBAppender;
DuckDBAppender appender = dbConn.createAppender("main", "books");
appender.beginRow();
appender.append("Refactoring Java");
appender.append(44.95);
appender.append(25);
appender.endRow();
appender.beginRow();
appender.append("Optimizing SQL");
appender.append(39.50);
appender.append(10);
appender.endRow();
appender.close();

Why use DuckDBAppender? It’s faster than INSERT statements and avoids SQL injection risks.

Read and Write Parquet Files in DuckDB via Java

Write to Parquet:

sql.execute("COPY books TO '/tmp/book_inventory.parquet' (FORMAT PARQUET)");

Read from Parquet:

ResultSet parquetData = sql.executeQuery("SELECT * FROM read_parquet('/tmp/book_inventory.parquet')");
while (parquetData.next()) {
    System.out.println(parquetData.getString("title"));
}

Cleanup

Always close your resources:

sql.close();
dbConn.close();

Conclusion

Using DuckDB in Java is straightforward, powerful, and efficient. With its embedded engine and tools like DuckDBAppender, you can process analytical data at lightning speed without external dependencies.

References

Background References

  1. (March 12, 2025). Java JDBC Client. *DuckDB*. Retrieved March 12, 2025 from https://duckdb.org/docs/stable/clients/java.html

About the Author

Joseph Horace

Horace is a dedicated software developer with a deep passion for technology and problem-solving. With years of experience in developing robust and scalable applications, Horace specializes in building user-friendly solutions using cutting-edge technologies. His expertise spans across multiple areas of software development, with a focus on delivering high-quality code and seamless user experiences. Horace believes in continuous learning and enjoys sharing insights with the community through contributions and collaborations. When not coding, he enjoys exploring new technologies and staying updated on industry trends.