Jakarta NoSQL is a comprehensive framework designed to simplify the integration of Java applications with various NoSQL databases. By providing a unified API and a set of powerful annotations, Jakarta NoSQL enables developers to seamlessly work with different NoSQL data stores while maintaining flexibility and productivity.
-
Increase productivity performing common NoSQL operations.
-
Rich Object Mapping integrated.
-
Java-based Query and Fluent-API.
-
It is designed to work with various NoSQL databases and can quickly adapt to support new types and behaviors through extensions.
-
Annotation-oriented using Jakarta Persistence-like naming when it makes sense.
Jakarta NoSQL provides one API for each NoSQL database type. However, it incorporates the same annotations from the Jakarta Persistence specification and heritage Java Persistence Architecture (JPA) to map Java objects. Therefore, with just these annotations that look like Jakarta Persistence, there is support for more than twenty NoSQL databases.
@Entity
public class Car {
@Id
private Long id;
@Column
private String name;
@Column
private CarType type;
//...
}The annotations from the Mapping API will look familiar to Jakarta Persistence developers:
Annotation |
Description |
|
Specifies that the class is an entity. This annotation is applied to the entity class. |
|
Specifies the primary key of an entity. |
|
Specifies the mapped column for a persistent property or field. |
|
Specifies a class whose mapping information is applied to entities that inherit from it. |
|
Declares a class whose instances are stored as an intrinsic part of an owning entity, sharing the identity of the entity. |
|
Specifies the inheritance mapping strategy for the entity class hierarchy. |
|
Specifies the discriminator column for the mapping strategy. |
|
Specifies the value of the discriminator column for the annotated entity type. |
|
Specifies how the values of a field or property are converted to a basic type or a type that can be persisted by a persistence provider. |
|
Declares a Java |
These annotations serve as a familiar and powerful toolkit for Java developers, enabling them to map Java objects to NoSQL databases similarly to how Jakarta Persistence works with relational data.
The Template interface is the central entry point for interacting with a NoSQL database in Jakarta NoSQL. It provides a consistent, high-level API for performing common persistence operations such as insert, update, delete, and query.
Jakarta NoSQL supports multiple interaction styles through the Template, including:
-
Basic CRUD operations
-
Fluent-style query builders
-
String-based queries with support for projections
Once you’ve annotated your entity, you can perform basic operations like insert, find, and delete using the Template instance.
@Inject
Template template;
Car ferrari = Car.builder()
.id(1L)
.name("Ferrari")
.type(CarType.SPORT)
.build();
template.insert(ferrari);
Optional<Car> car = template.find(Car.class, 1L);
template.delete(Car.class, 1L);Jakarta NoSQL provides a unified API with specialized support for a wide range of NoSQL databases, including but not limited to document, key-value, column-oriented, graph, and emerging models.
Jakarta NoSQL provides a fluent API for dynamic query construction, enabling expressive selection, update, and deletion operations without relying on string-based queries.
This API is designed for scenarios where queries must be built programmatically, such as dynamic filters, reusable query logic, or conditional operations, while remaining database-agnostic.
Select example:
List<Car> sportsCars = template.select(Car.class)
.where("type").eq(CarType.SPORT)
.orderBy("name")
.result();Update example:
template.update(Car.class)
.set("available").to(false)
.where("type").eq(CarType.CLASSIC)
.execute();Delete example:
template.delete(Car.class)
.where("type").eq(CarType.CLASSIC)
.execute();This fluent style makes query intent explicit (select, update, delete),
reduces the risk of errors common in string-based queries, and adapts naturally
to the capabilities of different NoSQL databases.
Jakarta NoSQL supports string-based queries using the Jakarta Common Query Language (JCQL). There are two main methods for executing these queries:
-
query(String)— executes a generic query that always returns entities and requires an explicitFROMclause. -
typedQuery(String, Class<T>)— maps results to either an entity or a projection class. Supports omitting theFROMclause when used with@Projection(from = …).
The query(String) method is useful for selecting full entity instances, deleting, or updating data. It always returns entity types and requires a FROM clause in the query.
List<Car> cars = template.query("FROM Car WHERE type = :type")
.bind("type", CarType.SPORT)
.result();
Optional<Car> one = template.query("FROM Car WHERE id = :id")
.bind("id", 42)
.singleResult();|
Important
|
You cannot use projections with query(String) — only entity classes are supported.
|
Use typedQuery(…) when you want to:
-
Retrieve data as a projection (using
recordand@Projection) -
Omit the
FROMclause when using@Projection(from = …)
This method supports the full query API — result(), stream(), and singleResult():
@Projection
public record TechCarView(String name, CarType type) {}
List<TechCarView> cars = template
.typedQuery("FROM Car WHERE type = 'SPORT'", TechCarView.class)
.result();You may also omit the FROM clause entirely if you annotate the projection with @Projection(from = Car.class):
@Projection(from = Car.class)
public record BudgetCar(String name, double price) {}
List<BudgetCar> cheapCars = template
.typedQuery("WHERE price < 100", BudgetCar.class)
.result();Both query(…) and typedQuery(…) support retrieving a single result wrapped in an Optional:
Optional<Car> car = template.query("FROM Car WHERE id = :id")
.bind("id", "c-001")
.singleResult();
Optional<BudgetCar> result = template
.typedQuery("WHERE price < 100", BudgetCar.class)
.singleResult();The Communication API defines a minimal and extensible foundation for interacting with NoSQL databases while preserving the native semantics and operational behavior of the underlying database implementation.
The API focuses on low-level lifecycle operations such as storing, retrieving, replacing, and removing data structures according to the capabilities and characteristics of the target database.
The Communication API is intentionally designed to support:
-
Minimal abstraction
-
Provider neutrality
-
Extensibility
-
Preservation of native database semantics
-
Low-level communication operations
Communication managers may be configured using mechanisms such as Java properties, environment variables, dependency injection, configuration files, or provider-specific communication contexts according to the underlying database implementation.
The key-value communication model represents interaction with NoSQL databases based on the association of a unique key to a value.
BucketManagerFactory factory = ...
BucketManager manager = factory.get("users");
KeyValueRecord record = ...
manager.put(record);
Optional<KeyValueRecord> result = manager.findByKey("user:10");
manager.deleteByKey("user:10");The document communication model represents interaction with NoSQL databases based on hierarchical and nested document structures.
DocumentManagerFactory factory = ...
DocumentManager manager = factory.get("users");
DocumentRecord record = ...
manager.put(record);
Optional<DocumentRecord> result = manager.findByKey("user:10");
manager.deleteByKey("user:10");Document records expose document elements through named structures.
DocumentRecord record = ...
Optional<String> name = record.get("name");The column-family communication model represents interaction with NoSQL databases based on sparse and partition-oriented column structures.
ColumnManagerFactory factory = ...
ColumnManager manager = factory.get("users");
ColumnRecord record = ...
manager.put(record);
Optional<ColumnRecord> result = manager.findByKey("user:10");
manager.deleteByKey("user:10");Column records expose sparse collections of columns associated with a logical record structure.
ColumnRecord record = ...
Optional<String> name = record.get("name");The graph communication model represents interaction with graph-oriented NoSQL databases based on connected structures composed of vertices, edges, and properties.
GraphManagerFactory factory = ...
GraphManager manager = factory.get("social");
Vertex vertex = ...
manager.put(vertex);
Optional<Vertex> result = manager.findVertexById("user:10");
manager.deleteVertexById("user:10");Edges represent relationships between vertices according to the semantics of the underlying database implementation.
Edge edge = ...
String type = edge.type();
String source = edge.source();
String target = edge.target();<dependency>
<groupId>jakarta.nosql</groupId>
<artifactId>jakarta.nosql-api</artifactId>
<version>1.1.0-M2</version>
</dependency>To learn more, please refer to the reference documentation, and JavaDocs.
This project is governed by the Eclipse Foundation of Conduct. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to codeofconduct@eclipse.org.
Having trouble with Jakarta NoSQL? We’d love to help!
Please report any bugs, concerns, or questions with Jakarta NoSQL to https://github.com/jakartaee/nosql.
