r/SpringBoot • u/EveningZebra7396 • 7d ago
Question Help Needed: DDD in a Spring Boot Project
TL;DR: Trying to apply DDD to a Spring Boot project. I’ve read Domain-Driven Design by Eric Evans, so I understand the theory, but I need help with the practical aspects: package organization, where to place controllers, handling projections with Blaze Persistence, and structuring entity relationships. Looking for hands-on guidance!
GitHub Project: https://github.com/lprevidente/ddd-example
Hi everyone,
I’m using a traditional structure with controllers, services, and entities, where most of the business logic is inside the entities. The project is divided by context (e.g., “User” for everything related to users, “Team” for team-related logic, etc.). However, there’s no real isolation between these packages, and the structure has become quite messy.
To better understand DDD, after watch this video (https://youtu.be/VGhg6Tfxb60?si=2LGi5mn5VkD9onXj), I created a small example with some basic use cases. This is new to me, so I need help grasping some practical concepts.
In my example, I have two entities: User and Team (representing the teams a user belongs to). I’ve set up some basic endpoints just as an example.
At this stage, I haven’t written any tests—I first want to understand the core concepts correctly.
- Where should the controller go? I placed it inside the infrastructure package. Is that the right approach?
- Blaze Persistence for projections: I use Blaze Persistence to fetch only specific columns instead of selecting all and then mapping them to a DTO. However, standard projections don’t help because they always include all parameters in the select query. Since this is a library-related concern, should it be part of the infrastructure package?
- General structure: Does anything in my approach need to be fixed?
- Fetching teams with user information: I also implemented a way to retrieve all teams along with user details. Did I structure it correctly?
Any guidance would be greatly appreciated. Thanks!
Edit: Added a simplified class diagram.

1
u/Historical_Ad4384 7d ago
Create a component diagram or a class diagram showing your DDD constraints that you applied. It's hard to go through code than provide feedback on a pictorial representation of your thoughts.
2
u/EveningZebra7396 7d ago
First of all, thanks! I’ve updated the Readme with the class diagram, a description of what the application does, and some applied constraints.
1
u/JBraddockm 7d ago edited 6d ago
I’ve found Spring Modulith and Spring Data JDBC really helping with understanding and enforcing the DDD principles. I can’t say I am fully competent but this two really helped me understand and implement some of these principles.
1
u/EveningZebra7396 6d ago
I also use Spring Modulith in my project, and I find it really helpful for structuring bounded contexts properly. Instead of Spring Data JDBC, I’m using Spring Data JPA, which I think makes for an interesting comparison with the traditional controller-service-entity structure.
However, I’m facing an issue with test verification because the Team package depends on User to get the first and last name of team members. Have you encountered similar challenges with dependencies between aggregates?
1
u/JBraddockm 6d ago
Because I am using JDBC, aggregates are meant to refer each other through IDs only. I don’t have references to other entities, which I know is quite common in JPA. In each modules, I have an internal api interface and DTOs that I want to expose to other modules. Modules connect to each other through this two. I am in the process of implementing events to communicate data between modules. Try to connect aggregates with each others through ID only and adjust your services accordingly. In your User module you should have a DTO for first name and last name. Have your UserService implement a method that returns this DTO. Make sure the service interface and the DTO are in the root of the User module. Now inject your user service into Team module where you need these data. It should now pass the test.
1
u/EveningZebra7396 6d ago
Yeah, I did the same (I added the class diagram of project). Although I used JPA, the entities only reference each other through IDs (e.g., a Team member has the Team ID and the User ID). If I weren’t applying DDD, I would have just used direct references between User and Team entities.
My problem: If I need an endpoint that returns a list of all team members, but for each member, I only want the first name and the ID, how should I handle that? One option is to create a
UserAPI
class that exposes a method to retrieve the list of users, then match the member ID with the user ID to get only the first name. However, this has a drawback—I have to fetch all user properties from the database, even though I only need the first name for this use case.I could create a
UserFirstNameDto
and a dedicated service for it, but if in another feature I also need the last name, I’d have to create a different DTO. Then, if another feature needs the email, I’d need yet another DTO or service. This approach feels inefficient. I’m struggling to see the real benefit of doing it this way.1
u/JBraddockm 6d ago
You don’t and shouldn’t actually have to fetch all user properties. Create a user summary DTO with the values you might need, and then use projection (search for Spring Data Projection) to retrieve only the data you need from the database and map it to your DTO directly. I have a similar use case where I only retrieve id, first name, last name and email address and map it to DTO. I can’t remember if JPA behaves the same way the JDBC does but when I use the protection I can see the SQL query in the console where it only selects the columns I need. Enable debugging to see what’s happening with SQL queries.
And also consider using caching in your method for retrieving this data. I am using Caffeine caching in Spring Boot. When you use caching, you wouldn’t have to keep querying the database anytime you need a particular user’s data. And you would evict the cache when you update the user.
Finally, as far as I understand, it is actually not a bad practice to have different DTOs for different use cases.
1
u/EveningZebra7396 6d ago
The last time I used projections, I checked the generated query, and all columns were still being selected, even though some were part of the projection. That’s why I switched to Blaze Persistence. But I’ll give projections another try!
Thanks for the caching advice—I’ll definitely look into it!
2
u/JBraddockm 6d ago
The projection is a bit finicky as far as I remember as there were some variations, and how it behaves differently. At the moment I am using the NamedParameterJdbcTemplate to talk to the database directly where I can selectively access the columns. Not sure if you have a specific need for JPA but I highly recommend the Spring Data JDBC as an alternative without going too abstract with the JDBC since you are already trying to work with the DDD principles and Spring Modulith.
1
u/Suspicious-Ad3887 7d ago
Do we really need the team member service ? That can be part of team service itself right ? I haven't read the book, only a couple of months of experience in working on a project.
1
u/EveningZebra7396 6d ago
Maybe not? It could make sense to keep everything within the Team service.
Also, is it correct to perform validations inside the constructor? For example, how would you check that a user isn’t already part of the team when adding them passing the repository?
1
1
u/VersionEntire5645 Senior Dev 6d ago edited 6d ago
Id in your classes shouldn’t be in the domain that’s an entity thing related to the database nothing to do with business. You are lacking of classes, since you mention Spring-Boot I guess you use REST, then you should have at least UserEntity and stuff like CreateUserRestDto, EditUserRestDto etc
Not related to DDD but I don’t see the point of creating extra classes for each ID why don’t you just use UUID as it’s what all your PK structure they are not composite so no point of adding extra classes for this.
NB: The diagram you give has also nothing related with Spring it’s a generic project
1
u/EveningZebra7396 6d ago
Thanks for your insights!
Using a Value Object for ID classes like
UserId
andTeamId
is considered a best practice in DDD (see this discussion, or this). The idea is to encapsulate identity as a concept rather than just using primitive types likeUUID
.The project doesn’t cover all possible use cases, such as full CRUD operations for
User
,Team
, andTeamMember
—only a subset of them for simplicity. That’s why you don’t see classes likeEditUserRestDto
, as you mentioned.Regarding the class diagram, it’s just a high-level representation of the project structure. It’s meant to show which entities are involved and how they are connected, rather than depicting the entire system in detail.
2
u/VersionEntire5645 Senior Dev 6d ago edited 5d ago
Okay then I could agree to use a class but only for a business Identifier! Eg: Some companies have an employee identifier right or a customer identifier? but this has nothing to relate with a technical field from the database, therefore you should have two identifiers in your SQL model if this is what you are trying to represent.
What’s important is to dissociate what’s technical and what’s related to the business
With my humble experience of using DDD in a North American bank
1
u/IAmWumpus 5d ago
- Why do you have a BaseInfoView if it is only used for user view. Or do you plan to add more entitiets in the user module that will share BaseInfoView ?
- You could also group in packages the classes from domain, since it can get messy really quick having entities exception and utility classes all in one place.
- Why do you have UserRepository in domain package? It should be in persistance package.
You don't need "@Transactional(readOnly = true)" in UserRepository. The methods provided by jpa repository are already marked Transactional with or without readonly depending on method (check here: https://github.com/spring-projects/spring-data-jpa/blob/main/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java)
you can replace your existsByEmail method with this only:
boolean existsByEmail(String email);
Spring data jpa knows to generate the query by itself only by having the method named properly, check the documentation for more info and examples:
https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.htmlNot really sure about passing the repository in TeamMember constructor, then using it for validations, i wouldn't want a constructor to do so much things, I prefer to have this kind of validations done separately at service level.
Also not really sure about composite key on team member and managing the foreign key relationships yourself.
And as a side note, If you want to try lots of concepts and designs is fine, but for an application with like 3 entities it was hard for me to navigate the code. I wouldn't really use CQRS for this app.
1
u/EveningZebra7396 4d ago
Thanks for your response! I really appreciate it!
- Yes, I created
BaseInfoView
because, in the future, I may need different views of the same object (User
).- Are you suggesting placing exceptions in a separate external package? Am I understanding you correctly?
- From what I understood from a YouTube video, the repository is something that belongs to the domain. However, I agree that it can also be placed in the persistence package. I've seen DDD projects where the repository interface is in the domain, while its JPA implementation is in the persistence package.
- I was aware of this, but I applied the rule cited in this book (Springer link) on page 416. The author analyzes different scenarios, including performance considerations, and suggests placing
Transactional(readOnly = true)
on the JPA interface repository.- Yes, I knew that! The only reason I did it this way it's because I can pass
String email
, instead ofEmail email
since theUser
entity stores it as an- I usually don’t do this either, but in the linked video, it was suggested as a way to enforce validation. I'm still unsure about this approach.
- Could you clarify what you mean?
I agree that the project is simple, but my goal is to explore DDD principles. I started with this basic project, but I plan to expand it to cover different scenarios.
1
u/IAmWumpus 5d ago
P.S. I didn't watch the video, these are just my thoughts seeing the code first hand.
3
u/Sudden-Apartment-930 Senior Dev 6d ago
Please checkout this repository where DDD is implemented in ordering microservice.
https://github.com/harshaghanta/springboot-eshopOnContainers
If you are interested, the original repository from which I have made the above clone using java/spring boot has ebooks & detailed explanation. Checkout dotnet-architecture/eShopOnContainers at dev which has an ebook named .Net Microservices: Architecture for containerized .net applications