Connecting to DB & JpaRepository CRUD
One interface, all CRUD operations for free.
Now that we have an @Entity, how do we save it to the database? Do we need to write INSERT INTO book... SQL? No. Spring Data JPA provides the JpaRepository interface, which gives us all CRUD operations for free.
The Amazon Fulfillment Center Analogy:
Imagine Amazon's massive warehouse in Hyderabad. As a seller, you don't walk into the warehouse and physically build a shelf for your product. You just hand the product to the warehouse manager. The manager knows how to store it, find it later, or throw it away.
In Spring Boot, JpaRepository is that warehouse manager. You just create an interface and extend JpaRepository. You don't write the implementation class. Spring Boot looks at your interface and dynamically writes the implementation code at runtime to save, find, update, and delete objects in the database!
- JpaRepository<T, ID>: An interface provided by Spring Data JPA.
•Tis your Entity type (e.g.,Book).
•IDis the data type of your Primary Key (e.g.,Long). - Built-in Methods: It instantly gives you
save(),findById(),findAll(),deleteById(), etc., without writing a single line of SQL.
Let's wire the database to our REST API.
package com.devinhyderabad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 1. The Magic Interface. Spring provides the implementation automatically.
interface BookRepository extends JpaRepository<Book, Long> {
// It's empty, but it has save(), findById(), findAll(), deleteById()!
}@RestController
@RequestMapping("/api/books")
class BookController {
// 2. Inject the repository
private final BookRepository bookRepository;
public BookController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
// 3. CREATE: Uses save() to insert into DB
@PostMapping
public ResponseEntity<Book> createBook(@RequestBody Book book) {
Book savedBook = bookRepository.save(book);
return ResponseEntity.status(HttpStatus.CREATED).body(savedBook);
}
// 4. READ ALL: Uses findAll()
@GetMapping
public List<Book> getAllBooks() {
return bookRepository.findAll();
}
// 5. READ ONE: Uses findById() and handles 404
@GetMapping("/{id}")
public ResponseEntity<Book> getBookById(@PathVariable Long id) {
return bookRepository.findById(id)
.map(book -> ResponseEntity.ok(book))
.orElse(ResponseEntity.notFound().build());
}
// 6. DELETE: Uses deleteById()
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
if (bookRepository.existsById(id)) {
bookRepository.deleteById(id);
return ResponseEntity.noContent().build(); // 204 No Content
}
return ResponseEntity.notFound().build();
}
}Test this in Postman:
- POST a book:
{"title":"Spring Guide","author":"Deva"} - GET all books. You will see your book has been assigned an ID!
- Restart your app. The data will be gone because H2 is in-memory, but the table was automatically created.
Interview Question: "How does Spring Data JPA provide implementations for your repository interfaces?"
Answer: Spring uses dynamic proxies. At application startup, it scans for interfaces extending Repository. It creates a proxy class that implements your interface, and routes method calls (like save() or findById()) to the default implementation provided by SimpleJpaRepository, which under the hood uses Hibernate to execute the actual SQL.
Enterprise Note: Notice the use of map() and orElse() with findById(). findById() returns an Optional<Book>. This functional programming style prevents NullPointerException and makes handling 404s very elegant.
Key Takeaways
- ✅ JpaRepository provides all CRUD operations with zero implementation code
- ✅ Spring uses dynamic proxies to create repository implementations at runtime
- ✅ findById() returns Optional — use map() and orElse() for clean handling
- ✅ JpaRepository<T, ID> is parameterised with your Entity and PK types
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login