Return to site

☕🗄️ JAVA RECORDS WITH SPRING DATA JPA: DTOs, NOT ENTITIES

· java

🔸 TLDR

Records are excellent Spring Data JPA DTOs, but poor JPA entities. Use entities for persistence, Records for transport, and map between them at the service boundary.

🔸 TRUTH

Java Records work very well with Spring Data JPA; but not as replacements for standard JPA entities.

Records are immutable and final, while JPA entities need a lifecycle compatible with persistence, including construction and state changes. The practical pattern is:

▪️ Keep mutable JPA entities inside the data and service layers

▪️ Expose immutable Records to controllers and clients

▪️ Convert explicitly between both models

🔸 1. DEFINE THE API MODEL

public record PostRecord(
 Long id,
 String title,
 List<PostCommentRecord> comments
) {
 Post toPost() {
 var post = new Post().setId(id).setTitle(title);
 comments.forEach(c ->
 post.addComment(c.toPostComment())
 );
 return post;
 }
}

The Record becomes a compact DTO for JSON and service boundaries, while toPost() rebuilds the entity graph for persistence.

🔸 2. FETCH THE COMPLETE GRAPH

@Query("""
 select p from Post p
 join fetch p.comments
 where p.id = :postId
 """)
Optional<Post> findWithCommentsById(Long postId);

Fetching comments explicitly prevents uninitialized lazy associations and reduces the risk of N+1 queries.

🔸 3. MAP INSIDE THE SERVICE

public PostRecord findPostRecordById(Long id) {
 return repository.findWithCommentsById(id)
 .map(Post::toRecord)
 .orElse(null);
}
@Transactional
public PostRecord insert(PostRecord record) {
 return repository
 .persist(record.toPost())
 .toRecord();
}

The service owns the conversion: entities stay persistence-focused, while callers receive immutable, serialization-friendly data.

🔸 TAKEAWAYS

▪️ Do not expose managed entities directly to the Web Layer

▪️ Fetch every association required by the Record

▪️ Keep conversion logic explicit and testable

▪️ Remember that merge may fetch the current state before applying updates and deletes

This separation gives you safer APIs, simpler JSON and fewer lazy-loading surprises. 🚀

#Java #SpringBoot #SpringDataJPA #JPA #Hibernate #JavaRecords #BackendDevelopment #SoftwareArchitecture

Go further with Java certification:

Java👇

Spring👇

SpringBook👇

JavaBook👇