Agent Skills: Spring Boot Data Layer for DDD

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. Covers aggregate roots with AbstractAggregateRoot, value object mapping, EntityGraph for N+1 prevention, and Spring Boot 4 specifics (JSpecify null-safety, AOT repositories). For DDD concepts and design decisions, see the domain-driven-design skill.

UncategorizedID: joaquimscosta/arkhe-claude-plugins/spring-boot-data-ddd

Install this agent skill to your local

pnpm dlx add-skill https://github.com/joaquimscosta/arkhe-claude-plugins/tree/HEAD/plugins/spring-boot/skills/spring-boot-data-ddd

Skill Files

Browse the full folder contents for spring-boot-data-ddd.

Download Skill

Loading file tree…

plugins/spring-boot/skills/spring-boot-data-ddd/SKILL.md

Skill Metadata

Name
spring-boot-data-ddd
Description
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. Covers aggregate roots with AbstractAggregateRoot, value object mapping, EntityGraph for N+1 prevention, and Spring Boot 4 specifics (JSpecify null-safety, AOT repositories). For DDD concepts and design decisions, see the domain-driven-design skill.

Spring Boot Data Layer for DDD

Implements DDD tactical patterns with Spring Data JPA and Spring Data JDBC in Spring Boot 4.

Technology Selection

| 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.

Core Workflow

  1. Define aggregate root → Extend AbstractAggregateRoot<T> for domain events
  2. Map value objects → Use @Embedded or @Converter for immutability
  3. Create repository interface → One per aggregate root, extend appropriate base
  4. Implement service layer@Transactional on public methods, one aggregate per transaction
  5. Add projections → Interface or record-based for read operations

Quick Patterns

See EXAMPLES.md for complete working examples including:

  • Aggregate Root with AbstractAggregateRoot and domain events (Java + Kotlin)
  • Repository with EntityGraph for N+1 prevention
  • Transactional Service with proper boundaries
  • Value Objects (Strongly-typed IDs, Money pattern)
  • Projections for efficient read operations
  • Auditing with automatic timestamps

Spring Boot 4 Specifics

  • JSpecify null-safety: @NullMarked and @Nullable annotations
  • AOT Repository Compilation: Enabled by default for faster startup
  • Jakarta EE 11: All imports use jakarta.* namespace
  • ListCrudRepository: New interface returning List<T> instead of Iterable<T>

ListCrudRepository (Spring Data 3.1+)

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.

Detailed References

Anti-Pattern Checklist

| 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 |

Critical Reminders

  1. One aggregate per transaction — Cross-aggregate changes via domain events
  2. Repository per aggregate root — Never for child entities
  3. Value objects are immutable — No setters, return new instances
  4. Flush before events — Call repository.save() before events dispatch
  5. Test with @DataJpaTest — Use TestEntityManager for setup