Перейти к основному содержимому

Hibernate и JPA — практический старт

Разработчику Архитектору

Hibernate и JPA — практический старт

JPA (Jakarta Persistence API) — стандарт ORM: работа с БД через объекты. Hibernate — основная реализация JPA в Java.

В Spring Boot обычно используют Spring Data JPA, а не EntityManager вручную.

База Spring: Первая программа на Spring · обзор ORM: 110.md · Spring Framework.


Зависимости (Maven)

В start.spring.io выберите: Spring Web, Spring Data JPA, H2 Database.

Или в pom.xml:

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

application.properties:

spring.datasource.url=jdbc:h2:mem:notes
spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Сущность

package com.example.notes;

import jakarta.persistence.*;

@Entity
@Table(name = "notes")
public class Note {

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

@Column(nullable = false, length = 500)
private String text;

protected Note() {}

public Note(String text) {
this.text = text;
}

public Long getId() { return id; }
public String getText() { return text; }
public void setText(String text) { this.text = text; }
}

Репозиторий

package com.example.notes;

import org.springframework.data.jpa.repository.JpaRepository;

public interface NoteRepository extends JpaRepository<Note, Long> {
}

Spring Data сгенерирует save, findAll, findById, deleteById без реализации.


REST-контроллер

package com.example.notes;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

@RestController
@RequestMapping("/api/notes")
public class NoteController {

private final NoteRepository repo;

public NoteController(NoteRepository repo) {
this.repo = repo;
}

@GetMapping
public List<Note> list() {
return repo.findAll();
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Note create(@RequestBody NoteCreate body) {
return repo.save(new Note(body.text()));
}

@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long id) {
if (!repo.existsById(id)) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
repo.deleteById(id);
}

public record NoteCreate(String text) {}
}
./mvnw spring-boot:run

Проверка

curl http://localhost:8080/api/notes
curl -X POST http://localhost:8080/api/notes \
-H "Content-Type: application/json" \
-d '{"text":"JPA работает"}'

Консоль H2: http://localhost:8080/h2-console (JDBC URL из application.properties).


Ключевые понятия

ТерминСмысл
Entityтаблица в виде класса
PersistenceContextкэш сессии Hibernate
ddl-auto=updateсхема подстраивается (только dev!)
Lazy loadingсвязи грузятся по требованию

Production: миграции через Flyway или Liquibase, не ddl-auto=update.


Дальше

  • связи @OneToMany, @ManyToOne;
  • @Transactional на сервисном слое;
  • JUnit 5 с @DataJpaTest.

См. также

Другие статьи этого же раздела в боковом меню (как на странице «О разделе»).