Spring Data JPA & Repositories
Objekte mit JPA-Entities auf Tabellen abbilden und CRUD kostenlos aus einem Repository-Interface erhalten, das du nie implementierst.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
BookVault's catalog has lived in a ConcurrentHashMap - it vanishes on restart. Time
to give it a real database. Doing that with raw JDBC means writing connection code,
SQL, and result-set mapping for every operation. Spring Data JPA removes almost
all of it: you describe your data as objects, declare a repository interface, and get
a full data-access layer you never implement.
Add the starter and a database
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>H2 is an in-memory database - perfect for learning and tests. Swapping to PostgreSQL later is just a driver and a URL.
Map an object to a table: the entity
An entity is a class JPA maps to a database table. Annotations describe the mapping:
@Entity
class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // primary key, auto-generated
@Column(unique = true, nullable = false)
private String isbn;
private String title;
private String author;
private int copies;
protected Book() {} // JPA needs a no-arg constructor
// constructor, getters…
}Think of an object's data as a parcel and the database table as a warehouse of
numbered shelves. The entity annotations are the shipping form taped to the
parcel: @Table says which warehouse, @Id is the shelf number, @Column labels
each field's slot. JPA reads the form to file the object away and to fetch it back
later - you never walk the warehouse aisles (write SQL) yourself.
The repository: CRUD you never write
Declare an interface extending one of Spring Data's repository types, and Spring generates the implementation at runtime:
interface BookRepository extends JpaRepository<Book, Long> {
// that's it — save, findById, findAll, delete, count… all provided
}JpaRepository<Book, Long> means "manage Book entities with a Long id." You
immediately get save, findById, findAll, deleteById, count, and more - fully
implemented, transactional, and typed.
@Service
class BookService {
private final BookRepository repository;
BookService(BookRepository repository) { this.repository = repository; }
Book add(Book book) { return repository.save(book); }
List<Book> all() { return repository.findAll(); }
}You wrote no SQL and no implementation
There is no BookRepositoryImpl anywhere. Spring Data creates a proxy that turns your interface methods into queries and executes them. In the next lesson you'll add custom finders just by naming methods.
BookVault's BookService currently stores books in a Map<String, Book>. Describe the
two things you add to move it to a real database with Spring Data JPA - one on the
Book class, one new type - and note why you never write a class that implements the
data-access methods.
How do you obtain CRUD operations for an entity in Spring Data JPA?
Key takeaways
- Spring Data JPA maps objects to tables (@Entity, @Id, @Column) and generates data-access code for you.
- spring-boot-starter-data-jpa + an H2 (or PostgreSQL) driver sets up JPA/Hibernate and a datasource automatically.
- An entity is a class mapped to a table; it needs an @Id and a no-arg constructor.
- Declaring a repository interface extending JpaRepository<Entity, Id> gives you save/findById/findAll/delete for free - you never write the implementation.
- Switching databases later is mostly a driver and a connection URL change.