home / skills / giuseppe-trisciuoglio / developer-kit / spring-boot-crud-patterns

This skill helps you implement feature-aligned CRUD services in Spring Boot 3.5+, aligning aggregates, repositories, and controllers with clean DTOs.

npx playbooks add skill giuseppe-trisciuoglio/developer-kit --skill spring-boot-crud-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (32)
SKILL.md
9.9 KB
---
name: spring-boot-crud-patterns
description: Provides repeatable CRUD workflows for Spring Boot 3 services with Spring Data JPA and feature-focused architecture. Use when modeling aggregates, repositories, controllers, and DTOs for REST APIs.
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
category: backend
tags: [spring-boot, java, ddd, rest-api, crud, jpa, feature-architecture]
version: 1.1.0
---

# Spring Boot CRUD Patterns

## Overview

Deliver feature-aligned CRUD services that separate domain, application, presentation, and infrastructure layers while preserving Spring Boot 3.5+ conventions. This skill distills the essential workflow and defers detailed code listings to reference files for progressive disclosure.

## When to Use

- Implement REST endpoints for create/read/update/delete workflows backed by Spring Data JPA.
- Refine feature packages following DDD-inspired architecture with aggregates, repositories, and application services.
- Introduce DTO records, request validation, and controller mappings for external clients.
- Diagnose CRUD regressions, repository contracts, or transaction boundaries in existing Spring Boot services.
- Trigger phrases: **"implement Spring CRUD controller"**, **"refine feature-based repository"**, **"map DTOs for JPA aggregate"**, **"add pagination to REST list endpoint"**.

## Instructions

Follow these steps to implement feature-aligned CRUD services:

### 1. Establish Feature Package Structure

Create feature/<name>/ directories with domain, application, presentation, and infrastructure subpackages to maintain architectural boundaries.

### 2. Define Domain Model

Create entity classes with invariants enforced through factory methods (create, update). Keep domain logic framework-free without Spring annotations.

### 3. Declare Repository Interfaces

Define domain repository interfaces in domain/repository that describe persistence contracts without implementation details.

### 4. Implement Infrastructure Adapters

Create JPA entities in infrastructure/persistence that map to domain models. Implement Spring Data repositories that delegate to domain interfaces.

### 5. Build Application Services

Create @Service classes with @Transactional methods that orchestrate domain operations, repository access, and DTO mapping.

### 6. Define Request/Response DTOs

Use Java records or immutable classes for API contracts. Apply jakarta.validation annotations for input validation.

### 7. Expose REST Controllers

Create @RestController classes mapped to /api endpoints. Return ResponseEntity with appropriate status codes (201 for POST, 204 for DELETE).

### 8. Write Tests

Unit test domain logic in isolation. Use @DataJpaTest and Testcontainers for integration testing of persistence layer.

## Prerequisites

- Java 17+ project using Spring Boot 3.5.x (or later) with `spring-boot-starter-web` and `spring-boot-starter-data-jpa`.
- Constructor injection enabled (Lombok `@RequiredArgsConstructor` or explicit constructors).
- Access to a relational database (Testcontainers recommended for integration tests).
- Familiarity with validation (`jakarta.validation`) and error handling (`ResponseStatusException`).

## Quickstart Workflow

1. **Establish Feature Structure**  
   Create `feature/<name>/` directories for `domain`, `application`, `presentation`, and `infrastructure`.
2. **Model the Aggregate**  
   Define domain entities and value objects without Spring dependencies; capture invariants in methods such as `create` and `update`.
3. **Expose Domain Ports**  
   Declare repository interfaces in `domain/repository` describing persistence contracts.
4. **Provide Infrastructure Adapter**  
   Implement Spring Data adapters in `infrastructure/persistence` that map domain models to JPA entities and delegate to `JpaRepository`.
5. **Implement Application Services**  
   Create transactional use cases under `application/service` that orchestrate aggregates, repositories, and mapping logic.
6. **Publish REST Controllers**  
   Map DTO records under `presentation/rest`, expose endpoints with proper status codes, and wire validation annotations.
7. **Validate with Tests**  
   Run unit tests for domain logic and repository/service tests with Testcontainers for persistence verification.

Consult `references/examples-product-feature.md` for complete code listings that align with each step.

## Implementation Patterns

### Domain Layer

- Define immutable aggregates with factory methods (`Product.create`) to centralize invariants.
- Use value objects (`Money`, `Stock`) to enforce type safety and encapsulate validation.
- Keep domain objects framework-free; avoid `@Entity` annotations in the domain package when using adapters.

### Application Layer

- Wrap use cases in `@Service` classes using constructor injection and `@Transactional`.
- Map requests to domain operations and persist through domain repositories.
- Return response DTOs or records produced by dedicated mappers to decouple domain from transport.

### Infrastructure Layer

- Implement adapters that translate between domain aggregates and JPA entities; prefer MapStruct or manual mappers for clarity.
- Configure repositories with Spring Data interfaces (e.g., `JpaRepository<ProductEntity, String>`) and custom queries for pagination or batch updates.
- Externalize persistence properties (naming strategies, DDL mode) via `application.yml`; see `references/spring-official-docs.md`.

### Presentation Layer

- Structure controllers by feature (`ProductController`) and expose REST paths (`/api/products`).
- Return `ResponseEntity` with appropriate codes: `201 Created` on POST, `200 OK` on GET/PUT/PATCH, `204 No Content` on DELETE.
- Apply `@Valid` on request DTOs and handle errors with `@ControllerAdvice` or `ResponseStatusException`.

## Validation and Observability

- Write unit tests that assert domain invariants and repository contracts; refer to `references/examples-product-feature.md` integration test snippets.
- Use `@DataJpaTest` and Testcontainers to validate persistence mapping, pagination, and batch operations.
- Surface health and metrics through Spring Boot Actuator; monitor CRUD throughput and error rates.
- Log key actions at `info` for lifecycle events (create, update, delete) and use structured logging for audit trails.

## Examples

### Input: Product Create Request

```json
{
  "name": "Wireless Keyboard",
  "description": "Ergonomic wireless keyboard with backlight",
  "price": 79.99,
  "stock": 50
}
```

### Output: Created Product Response

```json
{
  "id": "prod-123",
  "name": "Wireless Keyboard",
  "description": "Ergonomic wireless keyboard with backlight",
  "price": 79.99,
  "stock": 50,
  "createdAt": "2024-01-15T10:30:00Z",
  "_links": {
    "self": "/api/products/prod-123",
    "update": "/api/products/prod-123",
    "delete": "/api/products/prod-123"
  }
}
```

### Input: Product Update Request

```json
{
  "price": 69.99,
  "stock": 45
}
```

### Output: Updated Product Response

```json
{
  "id": "prod-123",
  "name": "Wireless Keyboard",
  "description": "Ergonomic wireless keyboard with backlight",
  "price": 69.99,
  "stock": 45,
  "updatedAt": "2024-01-15T11:45:00Z",
  "_links": {
    "self": "/api/products/prod-123"
  }
}
```

### Input: Delete Product

```bash
curl -X DELETE http://localhost:8080/api/products/prod-123
```

### Output: 204 No Content

```
HTTP/1.1 204 No Content
```

### Input: List Products with Pagination

```bash
curl "http://localhost:8080/api/products?page=0&size=10&sort=name,asc"
```

### Output: Paginated Product List

```json
{
  "content": [
    {
      "id": "prod-123",
      "name": "Wireless Keyboard",
      "price": 69.99,
      "stock": 45
    },
    {
      "id": "prod-456",
      "name": "Wireless Mouse",
      "price": 29.99,
      "stock": 100
    }
  ],
  "pageable": {
    "page": 0,
    "size": 10,
    "total": 2,
    "totalPages": 1
  },
  "_links": {
    "self": "/api/products?page=0&size=10",
    "next": null,
    "last": "/api/products?page=0&size=10"
  }
}
```

## Best Practices

- Favor feature modules with clear boundaries; colocate domain, application, and presentation code per aggregate.
- Keep DTOs immutable via Java records; convert domain types at the service boundary.
- Guard write operations with transactions and optimistic locking where concurrency matters.
- Normalize pagination defaults (page, size, sort) and document query parameters.
- Capture links between commands and events where integration with messaging or auditing is required.

## Constraints and Warnings

- Avoid exposing JPA entities directly in controllers to prevent lazy-loading leaks and serialization issues.
- Do not mix field injection with constructor injection; maintain immutability for easier testing.
- Refrain from embedding business logic in controllers or repository adapters; keep it in domain/application layers.
- Validate input aggressively to prevent constraint violations and produce consistent error payloads.
- Ensure migrations (Liquibase/Flyway) mirror aggregate evolution before deploying schema changes.

## References

- [HTTP method matrix, annotation catalog, DTO patterns.](references/crud-reference.md)
- [Progressive examples from starter to advanced feature implementation.](references/examples-product-feature.md)
- [Excerpts from official Spring guides and Spring Boot reference documentation.](references/spring-official-docs.md)
- [Python generator to scaffold CRUD boilerplate from entity spec.](scripts/generate_crud_boilerplate.py) Usage: `python skills/spring-boot-crud-patterns/scripts/generate_crud_boilerplate.py --spec entity.json --package com.example.product --output ./generated`
- Templates required: place .tpl files in `skills/spring-boot-crud-patterns/references/` or pass `--templates-dir <path>`; no fallback to built-ins. See `references/README.md`.
- Usage guide: [references/generator-usage.md](references/generator-usage.md)
- Example spec: `skills/spring-boot-crud-patterns/assets/specs/product.json`
- Example with relationships: `skills/spring-boot-crud-patterns/assets/specs/product_with_rel.json`

Overview

This skill provides repeatable CRUD workflows and patterns for Spring Boot 3 services using Spring Data JPA and a feature-focused architecture. It guides you to structure feature packages, model aggregates, declare repository ports, implement JPA adapters, and expose REST APIs with validated DTOs. The patterns prioritize domain boundaries, testability, and standard HTTP semantics for REST endpoints.

How this skill works

The skill inspects and prescribes a step-by-step architecture: domain, application, presentation, and infrastructure layers per feature. It defines domain-first aggregates and repository ports, shows how to implement Spring Data adapters and controllers, and recommends DTOs, validation, transaction boundaries, and testing strategies. It also includes generator tooling to scaffold boilerplate from an entity spec and references for progressive examples.

When to use it

  • Implement REST create/read/update/delete endpoints backed by JPA and Spring Data.
  • Refactor a monolith into feature-aligned packages and DDD-inspired aggregates.
  • Add DTO records, input validation, and consistent controller mappings for external clients.
  • Diagnose repository contracts, transaction boundaries, or pagination regressions.
  • Scaffold CRUD boilerplate from an entity specification for fast feature delivery.

Best practices

  • Colocate domain, application, presentation, and infrastructure per feature to preserve boundaries.
  • Keep domain objects framework-free; use adapters to translate to JPA entities.
  • Use immutable DTOs (Java records) and jakarta.validation annotations at the API boundary.
  • Wrap write use cases in @Transactional services and protect concurrency with optimistic locking when needed.
  • Write unit tests for domain logic and use @DataJpaTest with Testcontainers for persistence verification.

Example use cases

  • Create a Product feature with Product aggregate, ProductRepository port, ProductEntity adapter, ProductService, and ProductController mapped to /api/products.
  • Add pagination and sorting to a list endpoint using Spring Data Pageable and standardized page/size defaults.
  • Refine an existing controller to stop returning JPA entities directly and replace with mapped DTOs to avoid lazy-loading and serialization leaks.
  • Generate CRUD boilerplate from a JSON spec using the included Python generator and customize templates for your package layout.
  • Write integration tests that validate JPA mapping, repository queries, and transactional behavior with Testcontainers.

FAQ

Does this pattern require Spring Boot 3.5+?

Yes. The guidance assumes Spring Boot 3.5+ and Java 17+ features such as records and modern Jakarta APIs.

Can I expose JPA entities directly in controllers?

No. Avoid exposing JPA entities; map to immutable DTOs to prevent lazy-loading issues and leaking persistence concerns to API clients.