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>