Careeroza
PUT vs PATCH
Replace or Update Partly
- PUT replaces the whole resource. The client sends every field; a missing field becomes empty.
- PATCH changes only the fields that are sent. Everything else stays as it was.
- PUT is idempotent: sending the same request twice leaves the same result. PATCH is usually idempotent too, but does not have to be (e.g. "add 5 to stock").
Example
The difference in plain Java: PUT builds a new product from the request; PATCH copies only non-null fields onto the existing one.
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Object> stored = new LinkedHashMap<>();
stored.put("name", "Wireless Mouse");
stored.put("description", "2.4 GHz, silent clicks");
stored.put("price", 799);
stored.put("stock", 120);
Map<String, Object> request = new LinkedHashMap<>();
request.put("price", 749);
request.put("stock", 90);
// PUT: the request IS the new resource
Map<String, Object> afterPut = new LinkedHashMap<>();
for (String field : stored.keySet()) afterPut.put(field, request.get(field));
// PATCH: copy only the fields that were sent
Map<String, Object> afterPatch = new LinkedHashMap<>(stored);
request.forEach((field, value) -> { if (value != null) afterPatch.put(field, value); });
System.out.println("stored " + stored);
System.out.println("after PUT " + afterPut);
System.out.println("after PATCH " + afterPatch);
}
}Output
stored {name=Wireless Mouse, description=2.4 GHz, silent clicks, price=799, stock=120}
after PUT {name=null, description=null, price=749, stock=90}
after PATCH {name=Wireless Mouse, description=2.4 GHz, silent clicks, price=749, stock=90}PATCH in Spring
A simple and safe way: a request record whose fields are nullable wrapper types. null means "not sent, keep the old value".
public record ProductPatch(String name, String description,
BigDecimal price, Integer stock, String category) {}
@PatchMapping("/{id}")
public ResponseEntity<Product> patch(@PathVariable Long id, @RequestBody ProductPatch patch) {
return service.find(id).map(old -> {
Product updated = new Product(id,
patch.name() != null ? patch.name() : old.name(),
patch.description() != null ? patch.description() : old.description(),
patch.price() != null ? patch.price() : old.price(),
patch.stock() != null ? patch.stock() : old.stock(),
patch.category() != null ? patch.category() : old.category());
return ResponseEntity.ok(service.save(updated));
}).orElse(ResponseEntity.notFound().build());
}Example
curl -X PATCH localhost:8080/api/products/1 -H "Content-Type: application/json" -d '{"price":749.00}'Example output
{"id":1,"name":"Wireless Mouse","description":"2.4 GHz, silent clicks","price":749.00,"stock":120,"category":"Electronics"}Note: With this approach a client cannot set a field to null with PATCH. If you need that, use JSON Merge Patch (application/merge-patch+json) or a Map<String, Object> body.