Skip to main content

Command Palette

Search for a command to run...

Techniques to Update a Single Field Using PUT in Spring Data JPA (Without Overwriting the Whole Entity)

In the REST world, the PUT method often implies replacing an entire resource with a new version. However, in real-world business applications — where entities have many fields, relationships, and timestamps — you rarely want to replace the entire...

Published
5 min read
Techniques to Update a Single Field Using PUT in Spring Data JPA (Without Overwriting the Whole Entity)
T

I am Tuanh.net. As of 2024, I have accumulated 8 years of experience in backend programming. I am delighted to connect and share my knowledge with everyone.

1. Introduction — Why Updating a Single Field Is More Complex Than It Looks

1.1. The Common Misconception About PUT

Most developers assume that a PUT call should include all entity fields — even those unchanged. This leads to bulky payloads and race conditions. But in modern JPA usage, we can selectively update a single column without loading the full entity into memory.

This technique is particularly important in high-throughput systems (such as HRM, e-commerce, or document management microservices) where multiple updates may target different fields concurrently.

1.2. Example Scenario: Updating Only status of a Movie

Imagine we have a simple Movie entity in a movie management application:

@Entity
@Table(name = "movies")
public class Movie {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;
private String director;
private String genre;
private boolean published;

// Getters and setters omitted for brevity
}

Suppose you want to expose an API endpoint /movies/{id} using PUT to update only the published flag — without rewriting the entire record.

1.3. The Naïve Approach (and Why It’s Problematic)

A common implementation might look like this:

@PutMapping("/{id}")
public ResponseEntity<movie> updateMovie(@PathVariable Long id, @RequestBody Movie newMovie) {
return movieRepository.findById(id)
.map(movie -> {
movie.setPublished(newMovie.isPublished());
return ResponseEntity.ok(movieRepository.save(movie));
})
.orElse(ResponseEntity.notFound().build());
}

This code works but has a hidden cost — it loads the entire entity from the database, updates one field, and flushes everything back. In large tables or frequently accessed APIs, this causes unnecessary I/O and risks overwriting fields modified by other processes.

1.4. The Efficient Way — Using @Modifying and Custom Queries

Spring Data JPA allows direct field updates through JPQL without loading the entity. You can define a repository method like this:

public interface MovieRepository extends JpaRepository<movie, long=""> {

@Modifying
@Query("UPDATE Movie m SET m.published = :published WHERE m.id = :id")
int updatePublishedStatus(@Param("id") Long id, @Param("published") boolean published);
}

Then in your controller:

@PutMapping("/{id}/published")
@Transactional
public ResponseEntity<string> updatePublishedStatus(@PathVariable Long id, @RequestBody Map<string, boolean=""> payload) {
boolean newStatus = payload.get("published");
int updated = movieRepository.updatePublishedStatus(id, newStatus);
return updated > 0
? ResponseEntity.ok("Movie status updated successfully")
: ResponseEntity.notFound().build();
}

This approach directly executes a lightweight SQL UPDATE statement without reading the full row, reducing latency and memory usage.

For visualization, you can refer to this helpful diagram that explains how JPA translates JPQL updates directly to SQL:👉 JPA Update Flow Diagram

2. Deeper Analysis — What Happens Behind the Scenes

2.1. Transaction Boundary and Flush Behavior

The @Modifying annotation marks the query as a data-changing operation. Combined with @Transactional, Spring ensures that the operation runs in a single transaction and flushes automatically at commit time.

Without @Transactional, the update may not execute properly, especially if you use lazy-loaded persistence contexts.

Also note: because the entity isn’t loaded, the persistence context doesn’t track the updated field — meaning you won’t see the change until you fetch the entity again. This is a deliberate trade-off between speed and context consistency.

2.2. Handling Concurrency and Partial Updates Safely

If multiple threads or services may update different fields of the same record, field-level updates like this are ideal — since they don’t interfere with other columns.

However, if your entity has versioning (@Version), JPA will not automatically increment the version field when using direct JPQL updates. To maintain optimistic locking, you can manually handle version incrementing:

@Modifying
@Query("UPDATE Movie m SET m.published = :published, m.version = m.version + 1 WHERE m.id = :id")
int updatePublishedStatus(@Param("id") Long id, @Param("published") boolean published);

This preserves your optimistic concurrency model.

2.3. When Should You Still Use Full PUT or PATCH?

If your update involves multiple fields, relationships (like @OneToMany), or triggers cascading updates, the safer route is to fetch the entity, modify it, and let JPA manage the graph.

For APIs designed to update only partial data (like toggling booleans, setting flags, or updating metadata), this JPQL update pattern is ideal — performant, clean, and predictable.

You could even abstract this into a service utility that dynamically builds JPQL updates for any entity and field, much like a mini ORM patch layer.

For more visual insight into REST update semantics, this chart helps clarify when to use PUT vs PATCH:👉 REST PUT vs PATCH Comparison

3. Conclusion — Clean Code Meets Database Efficiency

Updating a single field in Spring Data JPA isn’t just about writing fewer lines of code — it’s about optimizing data flow between your service layer and the database. Using @Modifying with JPQL gives you:

  • Faster updates with less memory overhead
  • Clear transaction boundaries
  • Avoidance of overwriting unrelated fields
  • Cleaner, testable controller logic

As your application grows, these micro-optimizations add up to macro-level performance gains.

💬 What Do You Think?

Would you prefer this JPQL update method or a generic PATCH-based approach for partial updates?

Drop your question or opinion in the comments below — let’s discuss which strategy fits best for your real-world architecture.

Read more at : Techniques to Update a Single Field Using PUT in Spring Data JPA (Without Overwriting the Whole Entity)

More from this blog

T

tuanh.net

540 posts

Are you ready to elevate your Java, OOP, Spring, and DevOps skills? Look no further!