Add the order history endpoint
Java · Spring Boot · intermediate · modification
Order history for the new account page. One repository call fetches the customer's orders already sorted by the database, and the summary (item count, total) is computed from the order lines in the same read-only transaction, so the lazy lines load without errors. Tested with my test customer (4 orders): numbers match the admin panel.
Shop backend on Spring Boot 3.3 (Java 21, Gradle with the Spring Boot plugin), Spring Data JPA with Hibernate 6.5 on PostgreSQL. Spring Security requires authentication for every `/api/**` route; the principal is `com.acme.shop.auth.AppUser`, whose `getId()` is also the customer id. Existing entities in this package: `Order` (`@Table(name = "orders")`; `Long id`, `Long customerId`, `Instant placedAt`, `OrderStatus status` enum, never null, and `@OneToMany(mappedBy = "order") List<OrderLine> lines` with the default fetch type, no `@BatchSize` or `@Fetch`) and `OrderLine` (`int quantity` ≥ 1, `long unitPriceMinor`). `hibernate.default_batch_fetch_size` is not set. Every order has at least one line. An order has at most 50 lines; `quantity` is 1..999 and `unitPriceMinor` is from 0 up to, but not including, 10^9.
Requirements
- `GET /api/me/orders` returns the signed-in customer's orders, newest `placedAt` first (ties: higher id first), each as `{ "id", "placedAt", "status", "itemCount", "totalMinor" }`.
- `itemCount` is the sum of the order lines' `quantity`; `totalMinor` is the sum of `quantity * unitPriceMinor` over its lines (minor units, one currency per shop).
- No pagination: a customer has at most 200 orders. This endpoint backs the account page, one of the busiest in the app, so it must run a fixed number of SQL queries per request (at most 2), however many orders the customer has.
- Read-only: no schema changes.
Files touched
- src/main/java/com/acme/shop/order/OrderRepository.java
- src/main/java/com/acme/shop/order/OrderSummary.java
- src/main/java/com/acme/shop/order/OrderHistoryService.java
- src/main/java/com/acme/shop/order/OrderHistoryController.java
--- src/main/java/com/acme/shop/order/OrderRepository.java
package com.acme.shop.order;
+
+import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderRepository extends JpaRepository<Order, Long> {
+
+ List<Order> findAllByCustomerIdOrderByPlacedAtDescIdDesc(Long customerId);
}
--- src/main/java/com/acme/shop/order/OrderSummary.java
+package com.acme.shop.order;
+
+import java.time.Instant;
+
+public record OrderSummary(long id, Instant placedAt, String status, int itemCount, long totalMinor) {
+}
+
--- src/main/java/com/acme/shop/order/OrderHistoryService.java
+package com.acme.shop.order;
+
+import java.util.List;
+
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class OrderHistoryService {