Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

ORM Java: Веб-технологии

В основе любой программы лежит какая-то определённая предметная область. Например, графический редактор имеет дело с геометрическими примитивами, такими как отрезки, круги или квадраты, а сервисы доставки еды занимаются логистикой.

Предметная область включает в себя набор сущностей, которые взаимодействуют друг с другом, а также правила их взаимодействия, называемые бизнес-логикой. Правила, работающие в конкретной предметной области, никак не связаны ни с языком ни с фреймворком, на которых пишется программа. Более того, они вообще не имеют никакого отношения к программированию и существуют независимо.

Для упрощения описания предметной области и хранения её данных в приложениях применяют ORM. ORM — это специализированный фреймворк,который помогает моделировать предметную область и связывать её с базой данных

В этом уроке мы познакомимся с концепциями ORM на примере фреймворка Ebean, так как он имеет простой интерфейс и лёгок в настройке.

Подключение Ebean

// Файл build.gradle

// Подключаем плагин, который расширяет возможности Ebean
plugins {
  id 'io.ebean' version '12.11.5'
}

// Добавляем необходимые зависимости
dependencies {
  implementation 'io.ebean:ebean:12.11.5'
  // Позволяет генерировать миграции
  implementation 'io.ebean:ebean-ddl-generator:12.11.5'
  // Query builder. Позволяет строить запросы
  implementation 'io.ebean:ebean-querybean:12.11.5'
  // Позволяет автоматически выполнять миграции
  implementation 'io.ebean:ebean-migration:12.11.2'
  // Добавляет различные аннотации
  implementation 'io.ebean:ebean-annotation:7.3'
  // Обработчик аннотаций используется для генерации компонента запроса
  annotationProcessor 'io.ebean:querybean-generator:12.11.5'
}

Настройка

Конфигурирование ORM Ebean выполняется в файле application.yaml

# Файл src/main/resources/application.yml

datasource:
  # Задаём базу данных, к которой будет происходить подключение
  db:
  # Имя пользователя и пароль
    username: ""
    password: ""
    # Драйвер базы данных и URL
    # Используем embedded вариант базы H2
    # БД располагается в файле в текущей директории
    url: "jdbc:h2:./hexlet"

Миграции

Миграция – это SQL-запрос, который выполняется в базе данных при любом её изменении. Например, в данном случае запрос создаёт таблицу customer:

create table customer (
  id                            bigint generated by default as identity not null,
  name                          varchar(255),
  constraint pk_article primary key (id)
);

Ebean имеет встроенную поддержку для генерации миграций БД и их запуска. Для генерации миграции нужно выполнить метод main() генератора миграций:

// Файл src/main/java/project/MigrationGenerator.java

public final class MigrationGenerator {

    public static void main(String[] args) throws IOException {
        // Создаём миграцию
        DbMigration dbMigration = DbMigration.create();
        // Указываем платформу, в нашем случае H2
        dbMigration.addPlatform(Platform.H2, "h2");
        // Генерируем миграцию
        dbMigration.generateMigration();
    }
}

Чтобы не запускать метод вручную, можно создать для этого таску Gradle:

// Файл build.gradle

task generateMigrations(type: JavaExec) {
  classpath = sourceSets.main.runtimeClasspath
  mainClass = 'exercise.MigrationGenerator'
}

Запуск этой таски gradle generateMigrations сгенерирует файл миграции на основании модели.

Чтобы миграции выполнялись автоматически при старте Ebean, нужно добавить в файл application.yaml следующий код:

# Файл application.yaml
ebean:
  migration:
    run: true

Модель

Модель — это воплощение понятия предметной области в коде приложения. В Ebean каждая модель представлена классом в коде и таблицей в базе данных

// Файл src/main/java/project/domain/Customer.java

// Аннотация @Entity обозначает, что класс является моделью
@Entity
// Класс модели наследуется от класса io.ebean.Model
// Благодаря этому у модели появляется метод save() для добавления сущности в БД
public class Customer extends Model {

    // Аннотация обозначает, что поле класса является автогенерируемым первичным ключом
    @Id
    long id;

    String name;

    public Customer(String name) {
        this.name = name;
    }

    // Геттеры для получения значения полей
}

Query builder

Query builder — это конструктор запросов. Он предоставляет удобный, выразительный интерфейс для создания и выполнения запросов к базе данных. Цепочка вызовов методов поэтапно конструирует необходимый запрос.

// Вставка данных в таблицу

// Создаём новый экземпляр модели
Customer customer = new Customer("Andrey");
// И вызываем наследуемый метод save()
customer.save()

// Выборка данных

// Для каждой сущности автоматически создается компонент запроса
// с тем же именем, но с префиксом Q
// Например для Customer создается компонент запроса с именем QCustomer
Customer customer = new QCustomer()
    .name.equalTo("Ivan") // Ищем совпадение по имени
    .findOne();
    // Метод findOne() указывает на окончание запроса и выполняет его в базе данных

// Ebean автоматически конвертирует вернувшиеся данные в объекты модели
// и возвращает их наружу.

// Получение списка сущностей
List<Customer> customers = new QCustomer()
    .name.equalTo("Ivan")
    .orderBy() // Сортировка по id в порядке возрастания
        .id.asc()
    .findList();


// Модификация данных

new QCustomer()
  .id.equalTo(10)
  .asUpdate() // Преобразует запрос в UPDATE
    .set("name", "Rob") // Устанавливаем новое значение поля
    .update(); // Выполняем обновление


// Другие примеры запросов можно посмотреть в документации
// по ссылке в дополнительных материалах

Пример из вебинара

import exercise.domain.query.QCompany;

// Пейджинг

int companiesPerPage = 10; // Количество компаний на странице
int offset = 20; // Смещение

PagedList<Company> pagedCompanies = new QCompany()
    // Устанавливаем смещение
    .setFirstRow(offset)
    // Устанавливаем максимальное количество записей в результате
    .setMaxRows(companiesPerPage)
    // Задаём сортировку по имени компании
    .orderBy()
        .name.asc()
    // Получаем список PagedList, который представляет одну страницу результата
    .findPagedList();
// Получаем список компаний
List<Company> companies = pagedCompanies.getList();

// Получение данных одной компании по её имени

Company company = new QCompany()
    .name.equalTo("Google")
    .findOne();


// Получение списка всех компаний из базы

List<Company> companies = new QCompany().findList();

// Добавление новой компании в базу данных

Company newCompany = new Company("Apple");
// Благодаря наследованию класса модели от класса io.ebean.Model,
// на модели можно вызывать метод save() для добавления новой записи в базу
newCompany.save();

Дополнительные материалы

  1. Подключение Ebean
  2. Настройка Ebean
  3. Миграции
  4. Модель
  5. Примеры построения запросов при помощи Query builder

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Java-разработчик
Профессия
с нуля
Разработка приложений на языке Java
2 февраля 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу