JavaRush /Курси /Модуль 5. Spring /Лекція 154: Створення бази даних та сутностей для проєкту...

Лекція 154: Створення бази даних та сутностей для проєкту

Модуль 5. Spring
Рівень 25 , Лекція 3
Відкрита

Сьогодні зануримось у світ баз даних, проєктування сутностей і інтеграції всього цього в наш додаток. Якщо пам'ятаєте, у попередніх лекціях ми вже вивчали Spring Data JPA, ORM-аніотації, такі як @Entity, @Id, @Column, побудували репозиторії і навіть трохи попрацювали з базовими CRUD-операціями. Тепер час застосувати знання на практиці і зібрати докупи теорію і логіку для фінального проєкту.


1. Проєктування структури бази даних

Ми вже трохи говорили про те, як проєктувати базу даних у кількох попередніх лекціях. Тепер заглибимось у цей процес.

Часто саме від коректного проєктування бази даних залежить успіх вашого додатку. Уявіть собі історію, де дані неструктуровані або їх неможливо оперативно діставати. Це майже як розбиратися в купі коду без коментарів.

На практиці треба враховувати:

  • Логічні зв'язки між даними.
  • Оптимізацію запитів.
  • Уникнення надмірності.

Щоб краще візуалізувати процес, створимо ER-діаграму нашої бази даних. Для фінального проєкту припустимо, що ми робимо додаток для управління задачами (Task Management System), де користувачі можуть створювати задачі, ставити дедлайни і відстежувати їхній статус.

ER-діаграма

На основі вимог база даних може виглядати так:


    USER
    ---------------------
    id (PK)
    username
    email
    password
    role

    TASK
    ---------------------
    id (PK)
    title
    description
    deadline
    status
    user_id (FK -> USER.id)

Як видно, у нас два основні об'єкти: User і Task. Вони пов'язані між собою (User може мати багато Tasks, але кожна Task прив'язана лише до одного User).

  • USER:
    • Містить дані користувача (логін, email, пароль, роль тощо).
  • TASK:
    • Містить дані задачі (заголовок, опис, дедлайн, статус, посилання на власника).

2. Імплементація сутностей у коді

Переходимо до написання моделі даних у Spring-додатку. Ми будемо використовувати JPA-аніотації для визначення сутностей.

Клас User


package com.example.taskmanagement.model;

import jakarta.persistence.*;
import java.util.List;

@Entity
@Table(name = "users") // Вказуємо явно ім'я таблиці: в SQL "user" - зарезервоване слово
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Автоінкремент для первинного ключа
    private Long id;

    @Column(nullable = false, unique = true) // Логін має бути унікальним
    private String username;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String role; // Можна вказати роль, наприклад ADMIN або USER

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Task> tasks; // Зв'язок із задачами, ліниве (lazy) завантаження

    // Геттери, сеттери, конструктори...
}

Клас Task

Основні моменти:

  1. Зв'язок @OneToMany в класі User дає змогу отримати всі задачі користувача.
  2. Зв'язок @ManyToOne в класі Task дозволяє кожній задачі бути прив'язаною до одного користувача.
  3. Ми використовуємо LAZY завантаження, щоб при запиті користувача (або задачі) не тягнути одразу пов'язану сутність з бази.

3. Ініціалізація бази даних

Тепер, коли сутності готові, давайте створимо скрипти для заповнення бази тестовими даними. Можна використовувати H2 (локально) або PostgreSQL (для продакшн-середовища).

Скрипт для створення таблиць

Створимо файл schema.sql:


CREATE TABLE users (
    id BIGSERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    role VARCHAR(20) NOT NULL
);

CREATE TABLE tasks (
    id BIGSERIAL PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    description TEXT,
    deadline DATE NOT NULL,
    status VARCHAR(20) NOT NULL,
    user_id BIGINT NOT NULL,
    CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users (id)
);

Скрипт для наповнення тестовими даними

Файл data.sql:


-- Користувачі
INSERT INTO users (username, email, password, role) VALUES
('john_doe', 'john@example.com', 'password123', 'USER'),
('admin', 'admin@example.com', 'admin123', 'ADMIN');

-- Завдання
INSERT INTO tasks (title, description, deadline, status, user_id) VALUES
('Complete homework', 'Finish math and science homework', '2023-12-01', 'PENDING', 1),
('Fix server', 'Resolve critical issue on production server', '2023-11-25', 'IN_PROGRESS', 2);

Налаштування application.yml (H2 Database) Якщо хочете використовувати H2 і протестувати локально:


spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true

При запуску Spring Boot додаток автоматично створить таблиці, використовуючи анотовані сутності.


4. Перевірка роботи на практиці

Давайте напишемо репозиторії і протестуємо додавання даних.

Репозиторій для User


package com.example.taskmanagement.repository;

import com.example.taskmanagement.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);
}

Репозиторій для Task


package com.example.taskmanagement.repository;

import com.example.taskmanagement.model.Task;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface TaskRepository extends JpaRepository<Task, Long> {
    List<Task> findByUserId(Long userId);
}

Кілька рядків для тесту. Створіть тестовий сервіс або метод, щоб перевірити:


@Autowired
private UserRepository userRepository;

@Autowired
private TaskRepository taskRepository;

public void testDatabase() {
    User user = userRepository.findByUsername("john_doe");
    System.out.println("Користувач: " + user.getUsername());

    List<Task> tasks = taskRepository.findByUserId(user.getId());
    tasks.forEach(task -> System.out.println("Завдання: " + task.getTitle()));
}

Якщо все налаштовано правильно, ви повинні побачити дані з вашого data.sql в консолі.


На цьому етапі ви вже бачите основи роботи з базами в Spring-додатку: від опису сутностей до ініціалізації даних і створення зв'язків. Усе готове для додавання API на основі цих даних і реалізації бізнес-логіки в проєкті.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ