HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Для работы с базой данных Spring Boot использует Spring Data JPA (Jakarta Persistence API). Об этом механизме мы и поговорим в этом уроке.</p>
1 <p>Для работы с базой данных Spring Boot использует Spring Data JPA (Jakarta Persistence API). Об этом механизме мы и поговорим в этом уроке.</p>
2 <p>Цель Spring Data JPA - автоматизировать типовые операции по работе с базой данных, то есть создание, изменение, удаление и извлечение. В итоге вам приходится писать значительно меньше шаблонного кода при ручном взаимодействии с базой данных. В большинстве случаев весь необходимый SQL-код создается автоматически и не виден программисту.</p>
2 <p>Цель Spring Data JPA - автоматизировать типовые операции по работе с базой данных, то есть создание, изменение, удаление и извлечение. В итоге вам приходится писать значительно меньше шаблонного кода при ручном взаимодействии с базой данных. В большинстве случаев весь необходимый SQL-код создается автоматически и не виден программисту.</p>
3 <p>Работа этого механизма завязана на два элемента:</p>
3 <p>Работа этого механизма завязана на два элемента:</p>
4 <ul><li>Модель - класс, который соотносится с таблицей в базе данных (например, User)</li>
4 <ul><li>Модель - класс, который соотносится с таблицей в базе данных (например, User)</li>
5 <li>Репозиторий - класс, отвечающий за CRUD-операции над сущностью и ее коллекциями</li>
5 <li>Репозиторий - класс, отвечающий за CRUD-операции над сущностью и ее коллекциями</li>
6 </ul><p>Так этот механизм работает на практике:</p>
6 </ul><p>Так этот механизм работает на практике:</p>
7 <p>Spring Data JPA автоматически генерирует репозитории для модели на основе того, как модель проаннотирована. В свою очередь, аннотирование модели опирается на структуру таблицы в базе данных.</p>
7 <p>Spring Data JPA автоматически генерирует репозитории для модели на основе того, как модель проаннотирована. В свою очередь, аннотирование модели опирается на структуру таблицы в базе данных.</p>
8 <p>Предположим, что в нашей базе данных есть табличка<em>users</em>с такой структурой:</p>
8 <p>Предположим, что в нашей базе данных есть табличка<em>users</em>с такой структурой:</p>
9 <p>Создадим для нее модель и проаннотируем ее:</p>
9 <p>Создадим для нее модель и проаннотируем ее:</p>
10 <p>Обратите внимание, что аннотации импортируются из пакета Jakarta. Это происходит из-за неочевидного момента в терминах:</p>
10 <p>Обратите внимание, что аннотации импортируются из пакета Jakarta. Это происходит из-за неочевидного момента в терминах:</p>
11 <ul><li>JPA (Jakarta Persistence API) - это спецификация, то есть набор интерфейсов и аннотаций</li>
11 <ul><li>JPA (Jakarta Persistence API) - это спецификация, то есть набор интерфейсов и аннотаций</li>
12 <li>Spring Data JPA - это конкретная реализация этой спецификации</li>
12 <li>Spring Data JPA - это конкретная реализация этой спецификации</li>
13 </ul><p>Именно поэтому большая часть аннотаций берется из Jakarta. Аннотации, которые импортируются из других пакетов, не входят в стандарт JPA - это специфика самого Spring Boot или каких-то других пакетов.</p>
13 </ul><p>Именно поэтому большая часть аннотаций берется из Jakarta. Аннотации, которые импортируются из других пакетов, не входят в стандарт JPA - это специфика самого Spring Boot или каких-то других пакетов.</p>
14 <p>Сама по себе модель - это обычный POJO-класс с полями, геттерами, сеттерами и конструкторами, если нужно. Добавление аннотаций никак не влияет на сам класс, но зато оно помогает Spring Data JPA сгенерировать код репозитория.</p>
14 <p>Сама по себе модель - это обычный POJO-класс с полями, геттерами, сеттерами и конструкторами, если нужно. Добавление аннотаций никак не влияет на сам класс, но зато оно помогает Spring Data JPA сгенерировать код репозитория.</p>
15 <p>Аннотирование модели начинается с двух аннотаций на уровне класса:</p>
15 <p>Аннотирование модели начинается с двух аннотаций на уровне класса:</p>
16 <ul><li>Аннотация @Entity указывает, что эта модель считается сущностью, связанной с таблицей в базе данных</li>
16 <ul><li>Аннотация @Entity указывает, что эта модель считается сущностью, связанной с таблицей в базе данных</li>
17 <li>Аннотация @Table задает имя таблицы</li>
17 <li>Аннотация @Table задает имя таблицы</li>
18 </ul><p>С полями аннотирование работает чуть хитрее. По умолчанию любое добавленное поле в модель отображается на базу данных при условии сопоставления имен. Работает это так:</p>
18 </ul><p>С полями аннотирование работает чуть хитрее. По умолчанию любое добавленное поле в модель отображается на базу данных при условии сопоставления имен. Работает это так:</p>
19 <ul><li>Spring Data JPA выполняет запрос в базу и извлекает структуру таблицы</li>
19 <ul><li>Spring Data JPA выполняет запрос в базу и извлекает структуру таблицы</li>
20 <li>Поля транслируются из<em>snake_case</em>в<em>camelCase</em>и сравниваются</li>
20 <li>Поля транслируются из<em>snake_case</em>в<em>camelCase</em>и сравниваются</li>
21 <li>Если поле найдено, оно будет отображаться на базу данных во время работы с репозиторием</li>
21 <li>Если поле найдено, оно будет отображаться на базу данных во время работы с репозиторием</li>
22 </ul><p>Но иногда этого недостаточно. Для примера представим, что нам нужно создать уникальный индекс. В этом случае используется аннотация @Column с указанием на то, что нам нужна уникальность. Кроме уникальности, эта аннотация позволяет задать:</p>
22 </ul><p>Но иногда этого недостаточно. Для примера представим, что нам нужно создать уникальный индекс. В этом случае используется аннотация @Column с указанием на то, что нам нужна уникальность. Кроме уникальности, эта аннотация позволяет задать:</p>
23 <ul><li>Максимальную длину length</li>
23 <ul><li>Максимальную длину length</li>
24 <li>Отсутствие<em>null</em>-значений nullable</li>
24 <li>Отсутствие<em>null</em>-значений nullable</li>
25 <li>Имя колонки, если оно отличает от стандартного name</li>
25 <li>Имя колонки, если оно отличает от стандартного name</li>
26 </ul><p>Рассмотрим такой пример:</p>
26 </ul><p>Рассмотрим такой пример:</p>
27 <p>Особняком стоит история с идентификатором. Идентификатор играет особую роль не только с точки зрения базы данных, но и для JPA. Это важно, потому что идентификатор используется в SQL для поиска записей в базе данных. Поэтому для него есть свои аннотации:</p>
27 <p>Особняком стоит история с идентификатором. Идентификатор играет особую роль не только с точки зрения базы данных, но и для JPA. Это важно, потому что идентификатор используется в SQL для поиска записей в базе данных. Поэтому для него есть свои аннотации:</p>
28 <ul><li>Аннотация @Id, которая указывает, что именно это и есть идентификатор</li>
28 <ul><li>Аннотация @Id, которая указывает, что именно это и есть идентификатор</li>
29 <li>Аннотация @GeneratedValue(strategy = IDENTITY), которая определяет стратегию создания идентификатора. Внутри аннотации IDENTITY указывает, что идентификатор генерируется автоматически - его не нужно создавать</li>
29 <li>Аннотация @GeneratedValue(strategy = IDENTITY), которая определяет стратегию создания идентификатора. Внутри аннотации IDENTITY указывает, что идентификатор генерируется автоматически - его не нужно создавать</li>
30 </ul><h2>Репозиторий</h2>
30 </ul><h2>Репозиторий</h2>
31 <p>Мы уже можем использовать созданную сущность, но пока не получится сохранить ее в базу. Чтобы решить эту проблему, нам нужен репозиторий. Посмотрим пример кода:</p>
31 <p>Мы уже можем использовать созданную сущность, но пока не получится сохранить ее в базу. Чтобы решить эту проблему, нам нужен репозиторий. Посмотрим пример кода:</p>
32 <p>Репозиторий в исходных файлах - это интерфейс, помеченный аннотацией @Repository. Spring Data JPA берет этот интерфейс и создает из него класс, который автоматически подставляется в приложение. Об этом мы поговорим чуть позже.</p>
32 <p>Репозиторий в исходных файлах - это интерфейс, помеченный аннотацией @Repository. Spring Data JPA берет этот интерфейс и создает из него класс, который автоматически подставляется в приложение. Об этом мы поговорим чуть позже.</p>
33 <p>Набор методов для генерации определяется интерфейсом JpaRepository. Содержимое этих методов генерируется на основе того, как проаннотирована модель. Это позволяет держать репозитории пустыми, не используя дополнительные методы.</p>
33 <p>Набор методов для генерации определяется интерфейсом JpaRepository. Содержимое этих методов генерируется на основе того, как проаннотирована модель. Это позволяет держать репозитории пустыми, не используя дополнительные методы.</p>
34 <p>Это будет работать до тех пор, пока приложение не станет большим и сложным - тогда придется дописывать свои методы. Изучим пример встроенных методов:</p>
34 <p>Это будет работать до тех пор, пока приложение не станет большим и сложным - тогда придется дописывать свои методы. Изучим пример встроенных методов:</p>
35 <h2>Использование в коде</h2>
35 <h2>Использование в коде</h2>
36 <p>Использование репозитория в коде приложения базируется на инъекции зависимостей, которую мы изучим в одном из ближайших уроков. Пока просто запомним, как выполняется эта задача.</p>
36 <p>Использование репозитория в коде приложения базируется на инъекции зависимостей, которую мы изучим в одном из ближайших уроков. Пока просто запомним, как выполняется эта задача.</p>
37 <p>Предположим, что мы хотим использовать репозиторий в контроллере. Для этого нужно добавить соответствующее поле и пометить его аннотацией @Autowired. Во время работы программы Spring автоматически подставит объект репозитория, которым мы можем свободно пользоваться:</p>
37 <p>Предположим, что мы хотим использовать репозиторий в контроллере. Для этого нужно добавить соответствующее поле и пометить его аннотацией @Autowired. Во время работы программы Spring автоматически подставит объект репозитория, которым мы можем свободно пользоваться:</p>
38 <h2>Связь с базой данных</h2>
38 <h2>Связь с базой данных</h2>
39 <p>В реальных приложениях используют базы данных, подобные PostgreSQL. Для обучения или даже иногда для разработки можно пойти более простым путем - использовать базу данных H2, аналог SQLite. Эти базы данных работают внутри запущенного приложения. Другими словами, они не ставятся как отдельная программа, поэтому их не нужно настраивать и обслуживать. Данные в таких базах хранятся в файлах или в памяти, что еще проще. Мы пойдем именно по такому пути.</p>
39 <p>В реальных приложениях используют базы данных, подобные PostgreSQL. Для обучения или даже иногда для разработки можно пойти более простым путем - использовать базу данных H2, аналог SQLite. Эти базы данных работают внутри запущенного приложения. Другими словами, они не ставятся как отдельная программа, поэтому их не нужно настраивать и обслуживать. Данные в таких базах хранятся в файлах или в памяти, что еще проще. Мы пойдем именно по такому пути.</p>
40 <p>Для подключения этой базы данных нужно установить зависимость:</p>
40 <p>Для подключения этой базы данных нужно установить зависимость:</p>
41 <p>На этом все. Spring Boot автоматически создает базу данных в памяти и подключается к ней.</p>
41 <p>На этом все. Spring Boot автоматически создает базу данных в памяти и подключается к ней.</p>
42 <p>Для работы нам понадобится кое-что еще. Мы создали модель или даже несколько, но каким образом будут создаваться таблицы? В реальных приложениях для этого используется<a>Liquibase</a>и другие механизмы миграции. Мы же воспользуемся встроенным механизмом, который позволяет создавать схему базы данных и обновлять ее автоматически:</p>
42 <p>Для работы нам понадобится кое-что еще. Мы создали модель или даже несколько, но каким образом будут создаваться таблицы? В реальных приложениях для этого используется<a>Liquibase</a>и другие механизмы миграции. Мы же воспользуемся встроенным механизмом, который позволяет создавать схему базы данных и обновлять ее автоматически:</p>
43 <p>За реализацию этой возможности отвечает<a>Hibernate</a>, который используется под капотом Spring Data JPA.</p>
43 <p>За реализацию этой возможности отвечает<a>Hibernate</a>, который используется под капотом Spring Data JPA.</p>