SurrealDB Docs Logo

Enter a search query

Quick start

This guide will teach you the basics of using the SurrealDB SDK for Java to interact with a SurrealDB instance. We will cover topics such as installing the SDK, connecting to an in-memory database, and performing basic queries. For demonstration purposes, the presented queries follow the example of a library database.

Important

You can find a working example project implementing the queries described in the guide in our surrealdb-examples repository

Prerequisites

This guide assumes the following:

  • You have a basic understanding of Java and the Java Runtime Environment.
  • You have Java 8 or higher installed on your machine.
  • You have a suitable IDE installed, such as IntelliJ IDEA or Eclipse.

Setup

Install the SDK

The SurrealDB Java SDK is available on the Maven Central repository. You can install it using Gradle or Maven. Copy the relevant code snippet into your build.gradle or pom.xml file to add the SDK as a dependency.

The latest version of the SDK is currently 0.2.0

ext { surrealdbVersion = "0.2.0" } dependencies { implementation "com.surrealdb:surrealdb:${surrealdbVersion}" }

Initialize the SDK

The first step towards sending queries is instantiating the driver. In the following example we use a try-with-resources block to ensure the driver is properly closed after use. After instantiating the driver, we will connect to an in-memory database, and select our namespace and database.

SurrealDB.java
package me.yourname.example; import com.surrealdb.Surreal; public class SurrealDB { public static void main(String[] args) { // Instantiate the driver try (final Surreal driver = new Surreal()) { // Connect to an in-memory database driver.connect("memory"); // Select a namespace and database driver.useNs("example").useDb("example"); // ... } } }

Defining model classes

In order to represent database records within your application, you need to define POJO classes that match the tables in your database. Additionally, model classes require a public no-argument constructor to be used with the SDK.

For this example, we will create a Book class representing book records in our database.

Book.java
package me.yourname.surrealdb; import com.surrealdb.RecordId; import java.time.ZonedDateTime; public class Book { public RecordId id; public String title; public String author; public ZonedDateTime publishedAt; public boolean available; // A default constructor is required public Book() { } public Book(String title, String author, ZonedDateTime publishedAt, boolean available) { this.title = title; this.author = author; this.publishedAt = publishedAt; this.available = available; } @Override public String toString() { return "Book{" + "id=" + id + ", title='" + title + '\'' + ", author='" + author + '\'' + ", publishedAt=" + publishedAt + ", available=" + available + '}'; } }

Model classes are extremely useful as they can be used to represent more than just tables, such as complex query responses, relations, and more. Additionally, the fields in model classes can contain nested objects, arrays, and other SurrealDB data types.

You can learn more about supported SurrealDB data types on the data types page.

Using SDK methods

Creating new records

The first step towards querying data is to populate the database with records. This can be achieved using the create method, which allows you to pass model class instances to create new records.

In the following example, we instantiate a new Book object and pass it to the create method. This method will return a list of created Book records, each with a unique record id.

// Create a new book Book book = new Book( "Aeon's Surreal Renaissance", "Dave MacLeod", ZonedDateTime.parse("2024-10-15T00:00:00Z"), true ); // Create a book record Book created = driver.create(Book.class, "book", book).get(0); // Print the record id System.out.println("Created a new book with id " + created.id);

Since create allows us to create multiple records at once, it returns a list of books. In this case, we only created one book, so we use .get(0) to retrieve it.

You might also want to create records with a specific ID. In this case, you can pass the RecordId as the second argument to the create method. This approach will return the Book instance directly instead of a list.

// Create a book record with a custom id
Book created = driver.create(Book.class, new RecordId("book", "aeon"), book);

Selecting records

Now we have records in our database, we can query them using the select method. This method allows you to retrieve either all records from a table, or select a single record by its ID.

// Select all books Iterator<Book> books = driver.select(Book.class, "book"); while (books.hasNext()) { System.out.println("Found book: " + books.next().title); } // Select a specific book Optional<Book> aeon = driver.select(Book.class, new RecordId("book", "aeon")); aeon.ifPresent(value -> { System.out.println("Found book: " + value.title); });

While the select method is useful for retrieving all records or a single record by ID, you may want to perform filtering, ordering, and other operations on your select queries. In these situations you can use the query method to execute custom SurrealQL queries. We will cover this in the Complex queries section.

Updating records

Records can be updated using the update and upsert methods. These methods allow you to update all records of a table, or a single record by its ID.

In the following example we update the availability status of a book record. We pass the id of the record we want to update, the type of update we want to perform, and the updated record. The UpType.MERGE parameter tells the SDK to merge the updated record with the existing record, keeping any fields that are not present in the updated record.

After the update is applied, a new Book instance is returned with the updated fields.

// Modify an existing book record existing.available = false; // Update the book record Book updated = driver.update(Book.class, existing.id, UpType.MERGE, existing); // Print the book status System.out.println("New availability: " + updated.available);

You can pass a table name instead of a record ID to update all records in a table. This will return an iterator of updated records.

// Create an empty book instance Book update = new Book(); update.available = true; // Update all book records Iterator<Book> updated = driver.update(Book.class, "book", UpType.MERGE, update);

As you can see, we can instantiate an empty Book object and set only the fields we want to update. This allows us to conveniently update only specific fields.

Deleting records

Existing records can be deleted using the delete method. You can either pass a table name to delete all records in a table, or a record ID to delete a specific record.

// Delete a specific book driver.delete(new RecordId("book", "aeon")); // Delete all book records driver.delete("book");

Relating records

The Java SDK makes it easy to define relations between records using the relate method. This method takes two RecordId instances, an edge name, and an optional value model.

This next example demonstrates how to relate a book to a publisher.

RecordId bookId = new RecordId("book", "aeon"); RecordId publisherId = new RecordId("publisher", "surrealdb"); // Relate a book to a publisher driver.relate(bookId, "published_by", publisherId);

Much like other methods, you can also pass a class reference as a first argument to control the return and value type. This class must be a subclass of Relation, or simply Relation itself. This class holds the id, in, and out of a relation.

Relation relation = driver.relate(Relation.class, bookId, "published_by", publisherId); System.out.println("Related " + relation.in + " to " + relation.out + " with relation " + relation.id);

Custom queries

While the previously mentioned methods are useful for basic operations, you may want to perform more complex queries. This can be achieved using the query method, which allows you to execute custom SurrealQL queries.

You can pass a query string to the query method and it will return a Response object containing the query results.

Response response = driver.query("SELECT * FROM book WHERE available = true"); // Take the result of the first statement Value result = response.take(0);

You can optionally pass parameters to the query by using the queryBind method, which takes a map of values to bind to the query.

Response response = driver.queryBind( "SELECT * FROM book WHERE available = $status", Map.of("status", true) ); // Take the result of the first statement Value result = response.take(0);

Using values

While we can represent object data using model classes, we can also use the Value class to represent SurrealDB data types directly.

In all previous examples we can omit the model class reference arguments to make methods return a Value instance instead of a model class instance. This class provides useful functions to check and convert data types, as well as access nested objects and arrays.

Value result = driver.query("RETURN 123").take(0); // Check if the result is a long before casting if (result.isLong()) { System.out.println("Long value: " + result.getLong()); }

Next steps

Now that you have learned the basics of the SurrealDB SDK for Java, you can learn more about the API in the API documentation or explore the data types supported by the SDK.

© SurrealDB GitHub Discord Community Cloud Features Releases Install