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

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

Модуль 5. Spring
16 уровень , 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: " + user.getUsername());

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

Если всё настроено верно, вы должны увидеть данные из вашего data.sql в консоли.


На этом этапе вы уже видите основы работы с базами в Spring-приложении: от описания сущностей до инициализации данных и создания связей. Всё готово для добавления API на основе этих данных и обеспечения логики в проекте.

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