HTML Diff
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