Persistence and Transactions¶
Persistence maps application state to durable storage. ORM removes repetitive mapping code but does not remove SQL, transactions, indexes, or query costs.
Transaction boundary¶
Place a transaction around a coherent application operation, commonly in a service method.
@Service
final class LendingService {
private final BookRepository books;
LendingService(BookRepository books) {
this.books = books;
}
@Transactional
public void markUnavailable(UUID bookId) {
Book book = books.findById(bookId)
.orElseThrow(() -> new BookNotFoundException(bookId));
book.markUnavailable();
}
}
Declarative imperative transactions are commonly proxy-based and thread-bound. A call within the same object can bypass proxy advice, and starting unrelated threads does not automatically propagate the transaction. Default rollback rules are version/configuration-sensitive; state the intended policy explicitly when checked exceptions matter.
Entity design¶
- define identity and equality deliberately;
- protect invariants through methods rather than public setters;
- avoid using generated mutable identifiers in hash equality before persistence;
- use optimistic versioning when concurrent updates must detect conflicts;
- keep HTTP serialization separate from persistence navigation.
Query behavior¶
The N+1 problem occurs when loading a collection of parents triggers one additional query per parent for related data. Solve it per use case with fetch joins, entity graphs, projections, batching, or explicit queries—blanket eager loading can create different performance and cardinality problems. The lazy-versus-eager guide explains evaluation and resource-lifetime boundaries.
Pagination must include deterministic ordering. Fetching an entire table and then paging in memory is not database pagination. Inspect generated SQL and query plans.
External calls¶
Avoid holding a database transaction open across slow network calls. A database transaction cannot atomically cover an ordinary remote service. For cross-system workflows, study idempotency, the transactional outbox, sagas, and reconciliation.
See Spring's declarative transaction documentation.