Copy-paste Claude Code prompts for Spring Boot 3 — JPA entities, controllers, Liquibase migrations, Testcontainers tests. Java 21 + records-first.
Spring Boot is verbose by tradition — the right prompts collapse boilerplate without losing the explicitness Spring teams rely on. The templates below assume Java 21 + Spring Boot 3.3 and produce idiomatic, test-covered diffs.
Add an 'Order' resource.
Entity:
- id: UUID, generated
- customer: ManyToOne Customer (LAZY)
- status: enum OrderStatus stored as STRING
- totalCents: long, not null
- createdAt, updatedAt: auditing via @CreatedDate, @LastModifiedDate
- Optimistic locking via @Version on a long
Constraints:
- Read CustomerEntity.java and CustomerController.java FIRST. Match field
ordering, annotation style (one annotation per line), import order.
- Use the JpaRepository pattern in repository/.
- DTOs are Java 21 records: OrderCreateRequest, OrderResponse — separate from entity.
- Controller: @RestController + @RequestMapping("/api/v1/orders"), constructor
injection of OrderService.
- Service layer: OrderService is the only thing that touches OrderRepository.
- Liquibase changelog in db/changelog/changes/2026-05-19-add-order.xml — use
the changeSet style of the most recent file in that directory.
- Test: @SpringBootTest + Testcontainers Postgres + MockMvc. One happy-path
POST test, one 404 GET test.
GET /api/v1/orders returns slowly for accounts with > 200 orders. Spring's
hibernate.session.events.log shows the N+1.
Read OrderController, OrderService, OrderRepository, OrderEntity.
Identify each lazy association being touched in the response serialization:
- field name
- entity that owns it
- the line in the response mapper that triggers the lazy load
For each one, decide:
- Add @EntityGraph to the repository method, OR
- Add a fetch join in a custom @Query, OR
- Keep it lazy but add a batch size on the relationship (@BatchSize(size=50))
Pick ONE strategy across the whole endpoint — don't mix. Output the diff.
Write a Testcontainers integration test for the new OrdersController.
Constraints:
- Use the existing AbstractIntegrationTest base class in src/test/java/.../testing.
It already starts Postgres + Redis containers — do not declare new ones.
- @AutoConfigureMockMvc, no WebTestClient.
- Seed data via the existing TestDataFactory — never call repository.save() in
the test body.
- Cover: 201 create, 400 validation, 404 missing, 409 optimistic-lock conflict.
- Each test = one @Test method, named in test-purpose style:
shouldReturn404WhenOrderDoesNotExist.
- Use AssertJ for assertions. No Hamcrest.
## Stack
Java 21, Spring Boot 3.3, Postgres 16, Liquibase, Testcontainers, AssertJ.
Build: Maven. Lombok ALLOWED on entities, FORBIDDEN on DTOs (use records).
## Conventions
- Package-by-feature: com.acme.orders, com.acme.customers.
- Controllers thin (≤30 lines). Services own logic. Repositories only data access.
- DTOs are records in dto/. Never expose entities in the API.
- Validation via Jakarta @Valid on request bodies; @Validated on services.
- Tests: unit (Mockito) + integration (Testcontainers). No H2.
Related: Claude API from Java, testing prompts.