JavaRush /Курсы /Модуль 5. Spring /Практика: создание сущностей и репозиториев

Практика: создание сущностей и репозиториев

Модуль 5. Spring
5 уровень , 4 лекция
Открыта

Сегодня мы реализуем малую, но важную часть нашего приложения: создадим сущности и репозитории. Мы расширим функциональность нашего проекта, добавив работу с базой данных. В процессе работы мы будем шаг за шагом разбирать:

  1. Создание сущности — основа работы с JPA. Используем аннотации, такие как @Entity, @Id, @GeneratedValue и другие.
  2. Настройка репозиториев. Подключим JpaRepository и используем его стандартные методы.
  3. Практическая работа с CRUD-операциями. Сохраним, обновим, удалим и прочитаем данные из базы.

1. Постановка задачи

Представьте, что вы работаете над системой управления библиотечным каталогом. В рамках учебного примера мы создадим сущность Book, которая будет представлять книгу, и обеспечим базовые операции для взаимодействия с ней через базу данных. Наши задачи:

  • Создать сущность Book с полями id, title, author и publishedYear.
  • Реализовать для неё репозиторий.
  • Написать методы для сохранения и получения данных.

2. Создание сущности

Начнём с создания класса-сущности Book. Вспоминаем главное правило: сущности сопоставляют таблицы в базе данных. Каждое поле нашего класса становится колонкой в таблице. Для этого воспользуемся аннотациями @Entity, @Id, @GeneratedValue, @Column.

Откроем наш проект и добавим новый класс Book в пакет entity.


package com.example.library.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Column;

@Entity
public class Book {

    @Id // Указываем первичный ключ
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Автоматическая генерация ID
    private Long id;

    @Column(nullable = false) // Поле обязательное
    private String title;

    @Column(nullable = false)
    private String author;

    @Column(name = "published_year") // Указываем название колонки в базе
    private Integer publishedYear;

    // Конструкторы, геттеры, сеттеры
    public Book() {
    }

    public Book(String title, String author, Integer publishedYear) {
        this.title = title;
        this.author = author;
        this.publishedYear = publishedYear;
    }

    // Геттеры и сеттеры
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Integer getPublishedYear() {
        return publishedYear;
    }

    public void setPublishedYear(Integer publishedYear) {
        this.publishedYear = publishedYear;
    }
}

В коде:

  • @Entity — обозначает, что класс является сущностью и будет сопоставлен с таблицей в базе.
  • @Id — поле, которое будет использоваться в качестве первичного ключа таблицы.
  • @GeneratedValue(strategy = GenerationType.IDENTITY) — автоматическая генерация ID для новых записей.
  • @Column — настройка столбцов таблицы; добавили nullable = false, чтобы сделать поле обязательным.

Теперь, когда наша сущность готова, переходим к следующему шагу!


3. Создание репозитория

Репозиторий отвечает за операции с базой данных. В Spring Data JPA для этого используются интерфейсы, такие, как JpaRepository. Мы создадим интерфейс BookRepository и подключим стандартные методы.

Добавим новый интерфейс в пакет repository.


package com.example.library.repository;

import com.example.library.entity.Book;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
    // Здесь можно добавлять кастомные методы, если потребуется
}
  • JpaRepository<Book, Long> — тип Book указывает на нашу сущность, а Long — на тип её идентификатора.
  • Аннотация @Repository даёт понять Spring, что это компонент для работы с базой данных.

Встроенные методы JpaRepository

Получив наследование от JpaRepository, мы уже можем использовать методы, такие как:

  • save() — для сохранения объекта.
  • findById() — для поиска объекта по ID.
  • findAll() — для получения списка всех объектов.
  • deleteById() — для удаления объекта по ID.

4. Практическая работа: CRUD-операции

Теперь мы протестируем работу созданных сущностей и репозиториев. Для этого создадим базовый сервис и добавим тестовые данные.

Добавим новый сервис в пакет service.


package com.example.library.service;

import com.example.library.entity.Book;
import com.example.library.repository.BookRepository;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class BookService {

    private final BookRepository bookRepository;

    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    // Добавление книги
    public Book addBook(Book book) {
        return bookRepository.save(book);
    }

    // Получение всех книг
    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    // Поиск книги по ID
    public Optional<Book> getBookById(Long id) {
        return bookRepository.findById(id);
    }

    // Удаление книги по ID
    public void deleteBook(Long id) {
        bookRepository.deleteById(id);
    }
}

Теперь добавим контроллер, чтобы протестировать функциональность через HTTP-запросы.


package com.example.library.controller;

import com.example.library.entity.Book;
import com.example.library.service.BookService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/books")
public class BookController {

    private final BookService bookService;

    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @PostMapping
    public Book addBook(@RequestBody Book book) {
        return bookService.addBook(book);
    }

    @GetMapping
    public List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }

    @GetMapping("/{id}")
    public Book getBookById(@PathVariable Long id) {
        return bookService.getBookById(id).orElseThrow(() -> new RuntimeException("Book not found"));
    }

    @DeleteMapping("/{id}")
    public void deleteBook(@PathVariable Long id) {
        bookService.deleteBook(id);
    }
}

Для проверки работы можно отправлять запросы через Postman или аналогичный инструмент.


5. Запуск и проверка

  1. Запустите приложение на вашем локальном сервере.
  2. Проверьте базу данных, чтобы убедиться, что таблица book была создана.
  3. Используйте такие запросы:
    • POST /books с телом:
      
      {
        "title": "Spring in Action",
        "author": "Craig Walls",
        "publishedYear": 2021
      }
      
    • GET /books — для получения всех книг.
    • GET /books/{id} — для получения книги по ID.
    • DELETE /books/{id} — для удаления книги.

Поздравляем! Вы создали свою первую сущность и подключили её к базе с минимальными усилиями! Теперь ваш код стал ближе к реальному производству!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ