0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Репозитории, которыми мы пользовались в уроках этого курса, хранят свои данные в обычных переменных. Это было удобно для того, чтобы не отвлекаться на взаимодействие с базой и сфокусироваться на особенностях работы веба.</p>
1
<p>Репозитории, которыми мы пользовались в уроках этого курса, хранят свои данные в обычных переменных. Это было удобно для того, чтобы не отвлекаться на взаимодействие с базой и сфокусироваться на особенностях работы веба.</p>
2
<p>Теперь мы привыкли к фреймворку и понимаем принципы создания приложений на нем, поэтому можно начинать работу с реальной базой данных.</p>
2
<p>Теперь мы привыкли к фреймворку и понимаем принципы создания приложений на нем, поэтому можно начинать работу с реальной базой данных.</p>
3
<p>Чтобы начать хранить и извлекать данные из базы, нам нужно выполнить несколько действий:</p>
3
<p>Чтобы начать хранить и извлекать данные из базы, нам нужно выполнить несколько действий:</p>
4
<ol><li>Подключить пакеты, необходимые для работы с базой данных</li>
4
<ol><li>Подключить пакеты, необходимые для работы с базой данных</li>
5
<li>Настроить подключение к базе данных и дать к нему доступ из приложения</li>
5
<li>Настроить подключение к базе данных и дать к нему доступ из приложения</li>
6
<li>Создать начальную структуру базы данных с нужными таблицами</li>
6
<li>Создать начальную структуру базы данных с нужными таблицами</li>
7
<li>Переписать методы репозиториев так, чтобы они работали с данными через базу</li>
7
<li>Переписать методы репозиториев так, чтобы они работали с данными через базу</li>
8
</ol><p>В этом уроке мы проделаем все эти шаги на примере создания части CRUD для сущности Car с полями make (марка) и model (модель).</p>
8
</ol><p>В этом уроке мы проделаем все эти шаги на примере создания части CRUD для сущности Car с полями make (марка) и model (модель).</p>
9
<h2>Устанавливаем зависимости</h2>
9
<h2>Устанавливаем зависимости</h2>
10
<p>Для простоты мы будем использовать базу данных H2 с хранением в памяти. Этого достаточно в обучении, но в реальном окружении уже понадобится поставить PostgreSQL или его аналог:</p>
10
<p>Для простоты мы будем использовать базу данных H2 с хранением в памяти. Этого достаточно в обучении, но в реальном окружении уже понадобится поставить PostgreSQL или его аналог:</p>
11
<p>В дополнение к самой базе данных, нам понадобится пакет<a>HikariCP</a>. Он предоставляет пул соединений для работы в конкурентной среде, когда множество клиентов выполняют запросы одновременно. В такой ситуации одного соединения с базой данных будет недостаточно. Ниже мы увидим, как это работает.</p>
11
<p>В дополнение к самой базе данных, нам понадобится пакет<a>HikariCP</a>. Он предоставляет пул соединений для работы в конкурентной среде, когда множество клиентов выполняют запросы одновременно. В такой ситуации одного соединения с базой данных будет недостаточно. Ниже мы увидим, как это работает.</p>
12
<h2>Настраиваем подключение</h2>
12
<h2>Настраиваем подключение</h2>
13
<p>Рассмотрим такой пример:</p>
13
<p>Рассмотрим такой пример:</p>
14
<p>В примере выше мы создаем базу данных H2 с именем<em>hexlet_project</em>и расположением в памяти. После создания базы данных мы получаем переменную dataSource, через которую мы будем работать с базой. Доступ к ней нам будет нужен в репозиториях, потому что запросы должны быть сосредоточенны в них.</p>
14
<p>В примере выше мы создаем базу данных H2 с именем<em>hexlet_project</em>и расположением в памяти. После создания базы данных мы получаем переменную dataSource, через которую мы будем работать с базой. Доступ к ней нам будет нужен в репозиториях, потому что запросы должны быть сосредоточенны в них.</p>
15
<p>Поэтому нам нужно создать общий базовый класс для всех репозиториев со статическим полем для хранения этой переменой. Все остальные репозитории от него наследуются:</p>
15
<p>Поэтому нам нужно создать общий базовый класс для всех репозиториев со статическим полем для хранения этой переменой. Все остальные репозитории от него наследуются:</p>
16
<h2>Строим начальную структуру базы данных</h2>
16
<h2>Строим начальную структуру базы данных</h2>
17
<p>В нашем случае база данных создается при старте приложения, поэтому ее инициализацию мы будем делать там же, во время старта. Для этого создадим файл с нужной схемой данных и затем добавим ее в базу данных:</p>
17
<p>В нашем случае база данных создается при старте приложения, поэтому ее инициализацию мы будем делать там же, во время старта. Для этого создадим файл с нужной схемой данных и затем добавим ее в базу данных:</p>
18
<ol><li><p>Добавляем файл<em>src/main/resources/schema.sql</em>:</p>
18
<ol><li><p>Добавляем файл<em>src/main/resources/schema.sql</em>:</p>
19
</li>
19
</li>
20
<li><p>Во время инициализации базы данных загружаем схему в базу:</p>
20
<li><p>Во время инициализации базы данных загружаем схему в базу:</p>
21
</li>
21
</li>
22
</ol><h2>Создаем репозиторий CarRepository</h2>
22
</ol><h2>Создаем репозиторий CarRepository</h2>
23
<p>Перейдем к созданию репозитория:</p>
23
<p>Перейдем к созданию репозитория:</p>
24
<p>Принцип создания всех методов для работы с базой данных одинаковый:</p>
24
<p>Принцип создания всех методов для работы с базой данных одинаковый:</p>
25
<ul><li>Описываем шаблон запроса</li>
25
<ul><li>Описываем шаблон запроса</li>
26
<li>Получаем соединение</li>
26
<li>Получаем соединение</li>
27
<li>Формируем стейтмент</li>
27
<li>Формируем стейтмент</li>
28
<li>Делаем подстановки</li>
28
<li>Делаем подстановки</li>
29
<li>Выполняем запрос</li>
29
<li>Выполняем запрос</li>
30
<li>Собираем результат</li>
30
<li>Собираем результат</li>
31
<li>Возвращаем ответ</li>
31
<li>Возвращаем ответ</li>
32
</ul><h2>Рассматриваем примеры операций</h2>
32
</ul><h2>Рассматриваем примеры операций</h2>
33
<p>Структура контроллеров не меняется, несмотря на все изменения, которые мы сделали. Как видно на примере ниже, правильная организация абстракций и разделение по слоям приводят к тому, что изменение внутренностей не оказывает особого влияния на строение приложения:</p>
33
<p>Структура контроллеров не меняется, несмотря на все изменения, которые мы сделали. Как видно на примере ниже, правильная организация абстракций и разделение по слоям приводят к тому, что изменение внутренностей не оказывает особого влияния на строение приложения:</p>
34
34