DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • OpenSearch: Introduction and Data Management Patterns
  • Achieving Security and Trust in a Data Fabric: The Role of Zero Trust Architecture
  • Data Architectures in the AI Era: Key Strategies and Insights
  • Understanding the Differences Between Repository and Data Access Object (DAO)

Trending

  • Event Driven Architecture (EDA) - Optimizer or Complicator
  • Build a Simple REST API Using Python Flask and SQLite (With Tests)
  • Monolith: The Good, The Bad and The Ugly
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  1. DZone
  2. Data Engineering
  3. Data
  4. Domain-Driven Design: Manage Data With Jakarta Data and JNoSQL

Domain-Driven Design: Manage Data With Jakarta Data and JNoSQL

Learn how to simplify data management in DDD applications through practical examples of using domain-focused repositories and business semantics across databases.

By 
Otavio Santana user avatar
Otavio Santana
DZone Core CORE ·
Oct. 15, 24 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
4.7K Views

Join the DZone community and get the full member experience.

Join For Free

Managing data access in Domain-Driven Design (DDD) applications can be challenging, especially when working with different database types, like relational and NoSQL. This article explores how leveraging tools like JNoSQL and Jakarta Data helps simplify data access, making it easier to implement domain-focused repositories, integrate ubiquitous language, and naturally align business semantics with your code.

Understanding DDD vs. DAO

Before diving into the practical implementation details, it's essential to clarify the distinction between Domain-Driven Design (DDD) and the Data Access Object (DAO) pattern. Understanding this difference will help recognize the value of domain-focused repositories in DDD applications.

  • DAO focuses on low-level database operations, like queries and CRUD methods. It’s commonly found in heavily database-centric applications that push business logic into service layers. DAOs prioritize data persistence over domain semantics.
  • DDD, on the other hand, emphasizes the Ubiquitous Language—a shared vocabulary between the technical team and business stakeholders. This concept permeates the code, including repositories that abstract database access with meaningful domain actions. Instead of thinking about low-level database queries, you model operations like checkIn or reserve in the language of the business, keeping the domain and persistence logic closely aligned.
Aspect DAO (Data Access Object) DDD Repository (Domain-Driven Design Repository)
Focus Primarily on data persistence and CRUD operations Focuses on the domain model, representing business logic
Responsibilities Handles database access, queries, and low-level persistence Encapsulates domain logic, acting as an abstraction for the domain
Language Uses technical language (e.g., save, delete, query) Uses business-oriented language (e.g., checkIn, reserve)
Separation of Concerns Often combines database and business logic Keeps business logic in the domain, separating it from infrastructure
Transaction Handling May handle transactions directly Relies on the application service layer for transaction management
Use Case Suited for generic CRUD operations across various applications Tailored for domain-specific operations in DDD-based applications
Complexity Simpler, more focused on database-centric operations More complex, dealing with domain entities and business rules
Scalability Designed to handle data access in a straightforward way Scales with complex domain models and evolving business logic
Entity Lifecycle Focuses on managing the entity lifecycle at the database level Focuses on the lifecycle of domain entities and value objects
Data Source Primarily tied to one data source Can abstract over multiple data sources (e.g., NoSQL, relational)


While both patterns handle data persistence, they serve distinct purposes based on the complexity of the domain and business requirements. Understanding when to use each can help ensure your application's architecture aligns with its goals, whether focusing on straightforward data access or embedding rich business logic into your data layer.

DAO (Data Access Object) is the best choice for applications deeply rooted in database-centric architectures, where the primary concern is interacting with the database straightforwardly, such as performing CRUD (Create, Read, Update, Delete) operations. It is a valuable tool in scenarios where the business logic is simple or the application's primary focus is data storage and retrieval without complex domain rules. DAOs are particularly effective in such environments, where the persistence layer plays a significant role and decoupling business logic from database operations is less of a concern. DAO is a good choice if the goal is efficient data access without much domain complexity.

A DDD repository is ideal for more complex, domain-driven applications where business logic is central and you must align data operations with business semantics. The DDD repository pattern shines in scenarios where the domain model drives the application architecture—such as when dealing with rich business logic, evolving domain concepts, and multiple data sources. It provides a layer of abstraction that focuses on the domain, allowing developers to express business actions in the ubiquitous language. A DDD repository is the right fit if the goal is to maintain a clear separation between business logic and infrastructure while keeping the code aligned with business processes.

The new features in Eclipse JNoSQL 1.1.2 allow developers to create repositories focusing on domain semantics rather than database operations, enabling a more natural integration of DDD concepts.

Jakarta Data introduces an API that abstracts the complexities of data access across various databases, whether relational or NoSQL. This release empowers Java developers to interact with databases using repository interfaces that support custom queries and business actions without sacrificing NoSQL’s power or the database systems’ flexibility.

Eclipse JNoSQL 1.1.2 enhances Jakarta Data with features that allow you to write business actions using annotations, keeping the domain terminology consistent and explicit. This feature makes your code a direct reflection of the business model, bridging the gap between technical implementation and business requirements. For example, a hotel management system could utilize the language of “check-in,” “check-out,” and “reservation” to manage guest interactions with rooms.

This tutorial will build a simple Hotel Management System using Jakarta Data, Oracle NoSQL, and Helidon to register guests into rooms. This sample demonstrates how these features can help align your codebase with DDD principles.

Setting Up Oracle NoSQL and Helidon

To start, you’ll need to set up Oracle NoSQL on the cloud or run a standalone version. For a quick standalone setup, you can run the following Docker command:

Shell
 
docker run -d --name oracle-instance -p 8080:8080 ghcr.io/oracle/nosql:latest-ce


Next, create a Helidon project. Here’s how:

  1. Visit the Helidon Starter.
  2. Select Helidon MP as the flavor and proceed.
  3. Choose Quickstart for the application type and enable JSON-B media support.
  4. Configure your project with desired options like group and artifact ID.
  5. Generate and download the project.

Dependencies Setup

Once your Helidon project is generated, add the following dependencies in your pom.xml file:

XML
 
<dependency>
    <groupId>org.eclipse.jnosql.databases</groupId>
    <artifactId>jnosql-oracle-nosql</artifactId>
    <version>${jnosql.version}</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jnosql.metamodel</groupId>
    <artifactId>mapping-metamodel-processor</artifactId>
    <version>${jnosql.version}</version>
    <scope>provided</scope>
</dependency>


Configure the database properties:

Properties files
 
server.port=8181
jnosql.keyvalue.database=hotel
jnosql.document.database=hotel
jnosql.oracle.nosql.host=http://localhost:8080


We will model a Room as an entity and Guest as a value object. Here’s the code to define these:

Java
 
@Entity
public record Room (@Id String number, @Column Guest guest) {
}

@Embeddable(Embeddable.EmbeddableType.GROUPING)
public record Guest (@Column String documentNumber, @Column String name) {
}


In this design:

  • Room is an entity with its own lifecycle.
  • Guest is a value object, meaning it is embedded within the Room entity and not treated as a separate entity with its own lifecycle.

Creating the Repository

Now, let’s create a repository for managing hotel operations. This interface represents the business actions using domain semantics:

Java
 
@Repository
public interface Hotel {

    @Save
    Room checkIn(Room room);

    @Delete
    void checkOut(Room room);

    @Find
    Optional<Room> reservation(@By(org.soujava.samples.hotel._Room.NUMBER) String number);

    Page<Room> findBy(PageRequest pageRequest);
}


Here, we use annotations like @Save, @Delete, and @Find to represent meaningful actions in the domain, such as checking in and checking out guests.

The final step is to expose these operations through a REST API using JAX-RS:

Java
 
@Path("/hotels")
@ApplicationScoped
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class HotelResource {

    private final Hotel hotel;

    @Inject
    public HotelResource(Hotel hotel) {
        this.hotel = hotel;
    }

    @GET
    public List<Room> rooms(@QueryParam("page") int page, @QueryParam("size") int size) {
        var pageRequest = PageRequest.ofPage(page).size(size);
        return hotel.findBy(pageRequest).content();
    }

    @GET
    @Path("/{number}")
    public Room reservation(@PathParam("number") String number) {
        return hotel.reservation(number)
                .orElseThrow(() -> new WebApplicationException("Room not found", Response.Status.NOT_FOUND));
    }

    @PUT
    public Room checkIn(Room room) {
        return hotel.checkIn(room);
    }

    @DELETE
    @Path("/{number}")
    public void checkOut(@PathParam("number") String number) {
        hotel.checkOut(new Guest(number, null));
    }
}


Once your application is running, you can interact with it using cURL commands. Here’s an example:

Check-in a Guest:

Shell
 
   curl -X PUT -H "Content-Type: application/json" -d '{"number":101, "guest":{"name":"John Doe", "documentNumber":"12345"}}' http://localhost:8181/hotels


Get All Rooms:

Shell
 
curl -X GET http://localhost:8181/hotels


Check-out a Guest:

Shell
 
curl -X DELETE http://localhost:8181/hotels/101


Conclusion

The combination of Jakarta Data and Eclipse JNoSQL offers developers tools for organizing data access in ways that align with domain-driven design principles. By using these frameworks, developers can write repositories that reflect business logic while maintaining flexibility across various data sources. However, it’s important to consider potential challenges, such as managing multiple database types or tuning performance when working with large datasets. With thoughtful implementation, these tools can help structure applications in a way that supports both technical requirements and evolving business needs.

Source code: https://github.com/soujava/hotel-reservation-syntax

Domain-driven design Eclipse Data (computing) Data management

Opinions expressed by DZone contributors are their own.

Related

  • OpenSearch: Introduction and Data Management Patterns
  • Achieving Security and Trust in a Data Fabric: The Role of Zero Trust Architecture
  • Data Architectures in the AI Era: Key Strategies and Insights
  • Understanding the Differences Between Repository and Data Access Object (DAO)

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!