Jakarta Data and NoSQL – Standardized Data Access for Jakarta EE

The amount of data collected by applications nowadays is growing rapidly. Many of them need to support both relational SQL and non-relational NoSQL databases. Jakarta Data provides an API to allow easy data access. Developers can split the persistence mechanism and the model using common features like the Repository pattern and seamlessly switch between SQL and NoSQL databases or even use both in the same application.

What are NoSQL Databases?

NoSQL databases, also called “not only SQL”, “non-Relational” or “non-SQL”, are a type of database management system, where storage and querying data are performed differently from traditional ways used in relational databases.

Instead of the tabular structure of a relational database with tables and columns, NoSQL databases often use different data structures, like a JSON document or a graph structure. As the non-relational database design does not require a schema, it offers greater flexibility and scalability to manage large and usually unstructured data.

NoSQL also works well for distributed databases, where data is copied and stored on multiple servers, either locally or remotely. This improves availability and reliability of data. If some data is unavailable, the rest of the database can continue to run. While most relational database systems won’t work anymore, if say the list of schemas or tables is missing or corrupted.

Features of NoSQL Databases

While relational databases optimize storage and avoid redundancy, NoSQL databases can handle large amounts of unstructured or semi-structured data, offering scalability and flexibility for modern distributed applications.
The key features of NoSQL databases are:

  • Flexible data structures and dynamic schemas instead of fixed schemas
  • Horizontal scalability
  • Low latency
  • Large number of concurrent users and data volumes
  • Distributed nature
  • Higher performance and speed

Types of NoSQL Databases

The main types of NoSQL databases are:

  • Key-Value stores
  • Column-oriented
  • Document stores
  • Graph databases
  • Time series

Key-Value Stores

Key-value stores (databases) are the simplest type of NoSQL database. Data is stored in key-value pairs, essentially like a Map in the Java Collections API.

Examples of Key-value stores are Amazon DynamoDB, S3, Redis, Hazelcast or Memcached

Column-Oriented

Column-oriented databases store data in columns instead of rows, like relational databases do. This type of database is well-suited for mixing strucured, semi-structured and unstructured data, offering high concurrency and scalability.

Examples of Column-oriented databases are Apache HBase, Apache Cassandra, Sxylla, Clouddata, SimpleDB or Azure Cosmos DB.

Document-Oriented NoSQL

Document-oriented NoSQL databases store data in flexible documents, usually in JSON, BSON, or XML format, instead of rigid tables. These documents can have different structures, which is well-suited for applications that require variable data definitions and can enable faster, more agile development cycles.

Examples of document store NoSQL databases include MongoDB, CouchDB, Couchbase Server, Elasticsearch, Google Cloud Firestore, Amazon DocumentDB and DynamoDB.

Document Stores

Document stores allow to store, retrieve and edit documents in different formats like XML or more commonly JSON. Documents can be embedded inside other documents. Document stores are best suited for unstructured data like social media profiles, product sheets or content management.

Popular document stores include MongoDB, Couchbase, Apache CouchDB, Elastic or Oracle NoSQL Database.

Graph Databases

Graph databases allow to store more complex relationships than relational databases. The model graph applies graph theory, data is stored as a network of nodes and edges. Graph databases are well-suited for the “social graph” in social networks, but also AI models, especially Retrieval Augmented Generation (RAG) databases.

Examples for graph databases are Neo4J, ArangoDB, OrientDb, InfoGrid, Sones, HyperGraphDB or JanusGraph.

Time Series

A time series database can be seen as a specialized form of key-value store, with a timestamp as the key, and values associated with that timestamp.

Examples for time series databases are InfluxDB, KairosDB, TimescaleDB, Apache Pinot, Riak-TS or Prometheus.

Multi-Model

Some NoSQL databases combine more than one type, for example:

  1. OrientDB (Graph, Document)
  2. Couchbase (Key-value, Document)
  3. ArangoDB (Document, Graph, Key-value)
  4. Elasticsearch (Document, Graph)

SQL vs. NoSQL

These are the the main differences between SQL and NoSQL databases:

FeatureSQLNoSQL
SchemaFixedDynamic or none
ACID/BASEACIDBASE or limited ACID
Data ModelStructured, table-basedFlexible: documents, key-value, graphs
Data StructureNormalizedDenormalized
ScalabilityVertical scalingHorizontal scaling
Best Use CasesTransactional, flow-based applicationsBig Data, AI, Real time data analytics, embedded/IoT
Differences between SQL and NoSQL

ACID vs. BASE principles:

ACID

BASE

  • Atomicity
  • Consistency
  • Isolation
  • Durability
  • Basically Available
  • Soft state
  • Eventual consistency

Here are the most common keywords used by different database types:

SQLKey-ValueColumnDocumentGraph
TableBucketColumn familyCollection
RowColumnDocumentVertex
ColumnKey/value pairKey/value pairVertex and Edge property
RelationshipLinkEdge
Index
Keywords used by different database types

Using JPA for NoSQL databases can be problematic:

  1. Async Saves
  2. Aysnc Callback
  3. Time to Live (TTL)
  4. Consistency Level
  5. SQL based
  6. Diversity of NoSQL

This is where Jakarta Data and Jakarta NoSQL come into play.

Jakarta Data

Jakarta Data version 1.0 was released as part of Jakarta EE 11. It offers simplified data access to both relational and NoSQL databases. Applying common concepts like repositories and custom queries, known from popular data access libraries like Hibernate, Spring Data or Micronaut Data. Most of them support Jakarta Data or plan to do so in future versions.

Key elements of the Jakarta Data API are:

  • Repository
  • Order
  • Query
  • Sort
  • Page

Repository

Here is a Repository example:

@Repository
public interface Products extends DataRepository<Product, Long> {
    List<Product> findByPriceLessThan(float maxPrice);
    void save(Product product);
    ...
}

And how to use it:

@Inject
Products products;

products.save(new Product(1, "$25 gift card", 25.0f));

List<Product> found = products.findByPriceLessThan(100.0f);

Doing the same with the CrudRepository:

@Repository
public interface Products extends CrudRepository<Product, Long> {
    List<Product> findByPriceLessThan(float maxPrice);
    ...
}

Inherits methods like:

save(E entity);
saveAll(Iterable<E> entities);
findAll();
findById(K id);
existsById(K id);
delete(E entity);
deleteById(K id);
...

Allowing a more compact repository implementation.

Ordering and Sorting

An example for Ordering and a dynamic Query:

@Repository
public interface Products {
   Product findById(long productId);

   @OrderBy("price")
   List<Product> findByNameContains(String searchFor);


   @Query("UPDATE Product o SET o.price = o.price - (?2 * o.price) WHERE o.id = ?1")
   boolean discount(long productId, float discountRate);

   void save(Product p);
}

Applying Sort:

found = products.findByNameContains(namePattern, Sort.desc("price"));

Pagination

Jakarta Data supports both offset and cursor pagination.

Here’s an example for offset pagination, using a simple numerical offset:

@Repository
public interface BeerRepository extends BasicRepository<Beer, String> { }

Pageable page = Pageable.ofPage(1).sortBy(Sort.desc("style"));
Page<Beer> page1 = repository.findAll(page);
System.out.println("The first page:");
page1.forEach(System.out::println);

Pageable secondPage = page.next();
Page<Beer> page2 = repository.findAll(secondPage);
System.out.println("The second page:");
page2.forEach(System.out::println);

Cursor-based pagination uses a reference, rather than a simple offset, in this case a cursor to break records into pages:

@Repository
public interface FruitRepository extends BasicRepository<Fruit, String> {

    @Find
    CursoredPage<Fruit> cursor(PageRequest pageRequest, Sort<Fruit> order);

}

var pageRequest = PageRequest.ofSize(size).beforeCursor(PageRequest.Cursor.forKey(before));
var page = fruitRepository.cursor(pageRequest, DESC);

Event Handling

Jakarta Data further supports persistence life cycle events like:

void afterUpdate(@Observes PostUpdateEvent<Book> event) {
       // Perform post-update actions
}

Offering the same functionality without having to write e.g. database triggers.

Jakarta NoSQL

Jakarta NoSQL, while it started earlier than the factored-out Jakarta Data, released its 1.0 version in spring of 2025. The content of Jakarta EE 11 had already been finalized, so Jakarta NoSQL 1.1 aims for inclusion in Jakarta EE 12.

Jakarta NoSQL offers many annotations familiar to those in JPA, making it also blend-in well with Jakarta Data, especially if you switch between SQL and NoSQL databases:

AnnotationDescription
@EntityDefines a class as a persistable entity
@IdMarks the primary key of an entity
@ColumnMaps a property or field to a database column
@Embeddable, @MappedSuperclassEnable composition and inheritance
@ConvertHandles type conversion for persistence
Jakarta NoSQL Annotations

Repository

Using the compatible implementation Eclipse JNoSQL, you can define a very similar BeerRepository we saw earlier, but for a NoSQL database like the Oracle NoSQL Database:

import jakarta.data.repository.Query;
import jakarta.data.repository.Repository;
import org.eclipse.jnosql.databases.oracle.mapping.OracleNoSQLRepository;
 
@Repository
public interface BeerRepository extends OracleNoSQLRepository<Beer, String> {
 
    Set<Beer> findByStyle(String style);
 
    @Query("select * from Beer")
    Set<Beer> query();
}

Template

In addition to the Repository, Jakarta NoSQL also supports the Template interface to connect Java entities with NoSQL databases. Through this interface, you can perform standard CRUD operations and fluent queries with a consistent API.

Let’s take an example of a Car entity:

@Entity
public class Car {

    @Id
    private Long id;

    @Column
    private String name;

    @Column
    private CarType type;

    // Getters and setters...
}

And apply some simple CRUD operations using the template:

@Inject
Template template;

Car car = Car.id(1L)
             .name("Ferrari")
             .type(CarType.SPORT);

template.insert(car);

Optional<Car> result = template.find(Car.class, 1L);
template.delete(Car.class, 1L);

In addition to basic persistence, the Template interface also offers a typesafe and expressive fluent query API:

List<Car> cars = template.select(Car.class)
                         .where("type").eq(CarType.SUV)
                         .orderBy("name").asc()
                         .result();

template.delete(Car.class)
        .where("type").eq(CarType.COUPE)
        .execute();

Supported NoSQL Database Types

Eclipse JNoSQL currently supports the three most common types of NoSQL databases: key-value, column-based, document and graph.

Graph Databases

For graph databases JNoSQL builds on top of Apache TinkerPop, by which there are more than 30 supported NoSQL databases as of now.

Custom Annotations

For some NoSQL databases Eclipse JNoSQL offers custom annotations. Here an example for Apache Cassandra.

Entity:

@Entity("god")
public class God {

@Column
private String name;

@UDT("weapon")
@Column
private Weapon weapon;

}

Repository:

@Repository
interface GodRepository extends CassandraRepository<God, String> {

 @CQL("select * from God where name = ?")
   List<God> findByName(String name);

}

Conclusion

Jakarta Data and Jakarta NoSQL streamline the integration of Java applications with both relational and non-relational databases. Based on active and vibrant communities like Eclipse or Apache TinkerPop, and supported by some of the most popular Java persistence libraries including Hibernate, Micronaut or OpenLiberty, both Jakarta EE specs can help improve your data applications into a vendor-neutral future.

Featured in the special edition
JAVAPRO – Java 25 (Part 2)

Explore in-depth coverage of Java 25 and related topics in the full issue.

Discover the edition

Total
0
Shares
Previous Post

Java 25: The tl;dr Version

Next Post

How JCON Becomes Your Individual Highlight!

Related Posts