Spring Boot 4 data layer implementation for Domain-Driven Design. Use when implementing JPA or JDBC aggregates, Spring Data repositories, transactional services, projections, or entity auditing...
Implements DDD tactical patterns with Spring Data JPA and Spring Data JDBC in Spring Boot 4.
| Choose | When |
|---|---|
| Spring Data JPA | Complex queries, existing Hibernate expertise, need lazy loading |
| Spring Data JDBC | DDD-first design, simpler mapping, aggregate-per-table, no lazy loading |
Spring Data JDBC enforces aggregate boundaries naturally—recommended for new DDD projects.
See WORKFLOW.md for detailed step-by-step instructions with code examples.
See EXAMPLES.md for complete working examples including:
@NullMarked and @Nullable annotationsjakarta.* namespaceList<T> instead of Iterable<T>New repository interface returning List<T> for better API ergonomics:
// OLD: CrudRepository returns Iterable<T>
public interface UserRepository extends CrudRepository<User, Long> {
Iterable<User> findAll(); // Requires conversion to List
}
// NEW: ListCrudRepository returns List<T>
public interface UserRepository extends ListCrudRepository<User, Long> {
List<User> findAll(); // Direct List return
List<User> findAllById(Iterable<Long> ids); // Also List
}
// Can also extend both for full functionality
public interface UserRepository extends
ListCrudRepository<User, Long>,
ListPagingAndSortingRepository<User, Long> {
}
Benefits: No more StreamSupport.stream(iterable.spliterator(), false).toList() conversions.
| Need | Skill |
|---|---|
| DDD concepts and design | domain-driven-design |
| REST API for aggregates | spring-boot-web-api |
| Module boundaries | spring-boot-modulith |
| Repository testing | spring-boot-testing |
| Anti-Pattern | Fix |
|---|---|
FetchType.EAGER on associations |
Use LAZY + @EntityGraph when needed |
| Returning entities from controllers | Convert to DTOs in service layer |
@Transactional on private methods |
Use public methods (proxy limitation) |
Missing readOnly = true on queries |
Add for read operations (performance) |
| Direct aggregate-to-aggregate references | Reference by ID only |
| Multiple aggregates in one transaction | Use domain events for eventual consistency |
repository.save() before events dispatch@DataJpaTest — Use TestEntityManager for setup