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...

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
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.
1.2. Example Scenario: Updating Only status of a Movie
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
}
/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)
@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());
}
1.4. The Efficient Way — Using @Modifying and Custom Queries
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);
}
@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();
}
UPDATE statement without reading the full row, reducing latency and memory usage.
2. Deeper Analysis — What Happens Behind the Scenes
2.1. Transaction Boundary and Flush Behavior
@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.
@Transactional, the update may not execute properly, especially if you use lazy-loaded persistence contexts.
2.2. Handling Concurrency and Partial Updates Safely
@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);
2.3. When Should You Still Use Full PUT or PATCH?
@OneToMany), or triggers cascading updates, the safer route is to fetch the entity, modify it, and let JPA manage the graph.
3. Conclusion — Clean Code Meets Database Efficiency
@Modifying with JPQL gives you:
- Faster updates with less memory overhead
- Clear transaction boundaries
- Avoidance of overwriting unrelated fields
- Cleaner, testable controller logic
Read more at : Techniques to Update a Single Field Using PUT in Spring Data JPA (Without Overwriting the Whole Entity)





