Метод взаимодействия фреймворка с базой данных

Обновлено: 07.07.2024

В предыдущих постах о работе с базами данных в Spring Framework я поверхностно описал использование JdbcTemplate и NamedParameterJdbcTemplate. Пользоваться данными инструментами безусловно удобно, но у них есть определённые ограничения, среди которых:

  • Зависимость SQL-запросов от конкретной СУБД
  • Необходимость в самостоятельной реализации преобразования данных из БД в экземпляры классов-сущностей
  • Увеличение и усложнение кода при появлении новых таблиц и столбцов в таблицах

В стеке Spring существует проект Spring Data, реализующий большую часть тривиальных задач и упрощающий работу с источниками данных. В качестве источников данных могут использоваться как стандартные реляционные базы данных, так и NoSQL-хранилища вроде MongoDB или Redis.

В мире Java EE стандартом дефакто для работы с базами данных является JPA (Java Persistence API). Spring Data JPA, будучи частью Spring Data, реализует взаимодействие с реляционными СУБД, основываясь на JPA.

Настройка проекта

Для использования Spring Data JPA потребуются следующие зависимости:

Если используется Spring Boot:

Если Spring Boot не используется:

Классы-сущности (Entities)

Классы-сущности дополняются стандартными для JPA аннотациями. В качестве примера возьмём класс Person, использованный уже ранее:

Я добавил в этот класс несколько JPA-аннотаций:

  • @Entity указывает, что данный класс должен быть спроецирован в БД
  • @Id указывает, что свойство id является первичным ключом
  • @Column позволяет произвести более тонкую настройку проецирования свойства email класса в колонку таблицы БД

Репозитории

Главными компонентами для взаимодействий с БД в Spring Data являются репозитории. Каждый репозиторий работает со своим классом-сущностью. Самым простым способом создания репозитория является создание интерфейса с наследованием от CrudRepository, как показано в примере:

public interface PersonRepository extends CrudRepository < Person , String > <

Никаких дополнительных аннотаций для работы данного репозитория не требуется, более того, не требуется даже реализация. При инициализации контекста приложения Spring Data найдёт данный интерфейс и самостоятельно сгенерирует компонент (bean), реализующий данный интерфейс.

Существует несколько типов репозиториев, различающихся по набору возможностей:

И две реализации, которые можно использовать для каких-нибудь нетривиальных задач, вроде написания реализации какого-нибудь метода с нестандартным поведением:

Запросы

Стандартный набор методов для работы с данными, предоставляемый Spring Data, достаточно лаконичен. Мы можем найти все записи класса Person или найти запись по первичному ключу. А что, если нам требуется найти запись Person по email? Данную задачу можно решить несколькими способами.

Аннотация @NamedQuery в классе-сущности


Курс состоит из нескольких частей:


В качестве примера будем расматривать уже ставшее классическим — приложение списка дел. Для разработки приложения я буду использовать Visual Studio 2019(в Visual Studio 2017 процесс аналогичен).

Создание проекта


Назовем приложение и укажем путь к каталогу с проектом:


И выберем шаблон приложения API:


Модель

Создадим каталог Models и в новый каталог добавим первый класс TodoItem.cs, объекты которого будут описывать некоторые задачи списка дел в приложении:


В качестве СУБД мы будем использовать Sql Server, а доступ к базе данных будет осуществляться через Entity Framework Core и для начала установим фреймворк через встроенный пакетный менеджер NuGet:


Одним из подходов в работе с Entity Framework является подход «Code-First». Суть подхода заключается в том, что на основе модели приложения(в нашем случае модель представляет единственный класс — TodoItem.cs) формируется струткура базы данных(таблицы, первичные ключи, ссылки), вся эта работа происходит как бы «за кулисами» и напрямую с SQL мы не работаем. Обязательным условием класса модели является наличие поля первичного ключа, по умолчанию Entity Framework ищет целочисленное поле в имени которого присутствует подстрока «id» и формирует на его основе первичный ключ. Переопределить такое поведение можно с помощью специальных атрибутов или используя возможности Fluent API.

Главным компонентом в работе с Entity Framework является класс контекста базы данных, через который собственно и осуществляется доступ к данным в таблицах:


Базовый класс DbContext создает контекст БД и обеспечивает доступ к функциональности Entity Framework.

Для хранения данных приложения мы будем использовать SQL Server 2017 Express. Строки подключения хранятся в файле JSON под названием appsettings.json:


Далее нужно внести изменения в класс Startup.cs, добавив в метод ConfigureServices() следующий код:


Метод AddDbContext() настраивает службы, предоставляемые инфраструктурой Entity Framework Core для класса контекста базы EFTodoDBContext. Аргументом метода AddDbContext () является лямбда-выражение, которое получает объект options, конфигурирующий базу данных для класса контекста. В этом случае база данных конфигурируется с помощью метода UseSqlServer() и указания строки подключения.

Определим основные операции для работы с задачами в интерфейсе ITodoRepository:


Данный интерфейс позволяет нам не задумываться о конкретной реализации хранилища данных, возможно мы точно не определились с выбором СУБД или ORM фреймворком, сейчас это не важно, класс описывающий доступ к данным будет наследовать от этого интерфейса.
Реализуем репозиторий, который как уже сказано ранее, будет наследовать от ITodoRepository и использовать в качестве источника данных EFTodoDBContext:

Контроллер

Добавим в каталог Controllers класс TodoController.cs со следующим содержимым:

В своем конструкторе контроллер получает ссылку на объект типа ITodoRepository, но пока что инфраструктура MVC не знает, какой объект подставить при создании контроллера. Нужно создать сервис, который однозначно разрешит эту зависисмость, для этого внесем некотрые изменения в класс Startup.cs, добавив в метод ConfigureServices() следующий код:


Метод AddTransient<ITodoRepository, EFTodoRepository>() определяет сервис, который каждый раз, когда требуется экземпляр типа ITodoRepository, например в контроллере, создает новый экземпляр класс EFTodoRepository.

Полный код класса Startup.cs:

Миграции

Для того чтобы Entity Framework сгенерировал базу данных и таблицы на основе модели, нужно использовать процесс миграции базы данных. Миграции — это группа команд, которая выполняет подготовку базы данных для работы с Entity Framework. Они используются для создания и синхронизации базы данных. Команды можно выполнять как в консоли диспетчера пакетов (Package Manager Console), так и в Power Shell(Developer Power Shell). Мы будем использовать консоль диспетчера пакетов, для работы с Entity Framework потребуется установить пакет Microsoft.EntityFrameworkCore.Tools:


Запустим консоль диспетчера пакетов и выполним команду Add-Migration Initial:



В проекте появится новый каталог — Migrations, в котором будут хранится классы миграции, на основе которых и будут создаваться объекты в базе данных после выполнения команды Update-Database:


Web API готово, запустив приложение на локальном IIS Express мы можем протестировать работу контроллера.

Тестирование WebAPI

Создадим новую коллекцию запросов в Postman под названием TodoWebAPI:



Метод Create() после успешного создания задачи перенаправляет запрос на метод Get() с псевдонимом «GetTodoItem» и передает в качестве параметра Id только что созданной задачи, в результате чего в ответ на запрос мы получим созданный объект задачи в формате JSON.




На этом все, в следующей части реализуем пользовательский интерфейс с помощью JavaScript-фреймворка Angular.

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

Модуль Entity Framework Core

Entity Framework Core – технология объектно-ориентированного доступа к данным. При работе с базами данных через модуль EF Core запрошенная таблица преобразуется в экземпляр класса, а столбцы в одноименные свойства. Изменения значений свойств сохраняется в базе данных.

При работе с Entity Framework Core классы модели базы данных сопоставляются таблицам базы. Инкапсуляция реляционных запросов превращает работу с базами данных в «обычное» объектно-ориентированное программирование. В отличие от этого драйверы реляционного доступа, возвращают данные в виде таблицы или параметров, которые требуют дополнительной обработки.

Установка необходимых пакетов NuGet

Для использования возможностей объектно-реляционного сопоставления «объект - база данных» необходима установка приложение пакета Microsoft.EntityFrameworkCore.

Кроме этого, понадобится установка расширений SqlServerDbContextOptionsExtensions. UseSqlServer для этого необходимо в веб приложение добавить пакет Microsoft.EntityFrameworkCore. SqlServer. Это необходимо для настройки контекста и создания строк подключения с помощью построителей.

База данных для исследования


Создадим базу данных MS SQL. Для этого необходим MS SQL Server или MS SQL Server Express и MS SQL Server Management Studio. Создавать таблицы и связи между ними будем посредством инструмента управления MS SQL Server Management Studio. Базу данных назовем DBMSSQL. Добавим в базу три небольшие таблицы кратко описывающие науки и ее разделы.

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

  • PK (primary key) – первичный ключ
  • FK (foreign key) – ключ внешней связи
  • UI (unique index) – уникальный индекс

Модель базы данных

Модуль Entity Framework Core осуществляет доступ к базам данных посредством моделей. Модель – классы, определенные в соответствии таблицам базы данных. Entity Framework Core сопоставляет столбец таблицы и одноименное свойство класса соответствующей таблицы данных.

Соответственно таблицам создадим классы модели для базы данных DBMSSQL. Все таблицы в базе имеют одинаковые столбцы Id, Name, NumberViews, Uri. Чтобы уменьшить количество повторного программного кода создадим абстрактный класс с общими свойствами. Далее этот класс унаследуют классы модели базы данных.

Листинг модели базы данных:

Контекст сеанса с базой данных DBContext

Контекст баз данных представляется классом DBContext, необходимым для взаимодействия с базами данных. Объект класса производного от DBContext позволяет выполнять запросы и сохранять изменения, произведенные над свойствами экземпляров модели.

Во время взаимодействия с базой данных класс контекста наполняет классы модели информацией из таблиц базы данных. Сеанс взаимодействия контекста с базой данных краток, и состоит из одного цикла:

  • Создание объекта класса контекста
  • Получение данных (сохранение изменений)
  • Закрытие сеанса и удаление экземпляра контекста

Для наполнения классов модели информацией из базы в классе контекста необходимо определить свойства DbSet<TEntity>, где роль сущности (Entity) будут исполнять классы модели.

Класс DbSet<TEntity> - это оболочка для сущности (типа объекта таблицы базы данных), которой являются классы модели. Включение экземпляра класса DbSet<TEntity> в контекст означает, что он включен в модель Entity Framework Core. Свойства DbSet<TEntity> автоматически инициализируются при создании экземпляра класса контекста. Имена свойств, представляющих классы модели, должны быть идентичны названиям соответствующих таблиц в базе данных.

В принципе этих определений уже достаточно для работы с базами данных. Вся черновая работа скрыта инкапсуляцией, что вызывает приятное созерцание минимализма программного кода.

Листинг класса контекста для взаимодействия с базой данных DBMSSQL:

Строка подключения к SQL серверу

Реквизиты подключения к определенной базе данных, для контекста, указываются в строке подключения (connection string). Строку подключения к MS SQL Server удобно создавать с помощью построителей. Например, с помощью класса SqlConnectionStringBuilder, входящего в состав пространства имён Microsoft.Data.SqlClient (пакет Microsoft.EntityFrameworkCore.SqlServer). Таким способом создаётся синтактически правильная строка подключения к серверу базы данных.

Строка подключения отправляет серверу информацию для идентификации клиента, способе проверки клиента и выборе базы данных для последующих запросов. Разные режимы проверки подлинности пользователя требуют соответствующее содержание строки подключения.

Листинг двух вариантов строк подключения к SQL серверу:

Выполнение запросов к базе данных

Подключение к базе данных в веб приложении происходит при создании экземпляра класса контекста SqlDBContext. Экземпляр контекст создаётся в конструкторе контроллера HomeController.

После создания объекта контекста можно выполнять запросы к базе данных. В представления полученная информация передаётся в виде слабо-типизированных ViewBag и строго-типизированных объектов посредством Model.

Представление с моделью

Листинг представления с моделью:

Представление с ViewBag

Полученные данные можно передавать в представления динамическими переменными. Слаботипизированная переменная ViewBag может передавать любой объект, и что удобно, не требует приведения типов при присваивании соответствующему объекту.

В нашем случае в представление передаются списки объектов с информацией, полученной из базы данных. Путём перебора элементов списков, используя минимум кода Razor и разметки HTML, информация выводится в браузер в удобочитаемом виде.

Листинг представления с применением динамического свойства ViewBag:

Источники данных — это элементы управления, которые можно разместить на странице Web Forms и настроить аналогично другим элементам управления. Visual Studio предоставляет удобный набор диалоговых окон для настройки и привязки элементов управления к страницам Web Forms. Разработчики, которые не пишут или почти не пишут код, предпочитают этот метод с первого выпуска Web Forms.

обозревателе решений

Entity Framework

EF Code First

Чтобы быстро приступить к привязке взаимодействий с базой данных, начните с объектов класса, с которыми вы хотите работать. EF предоставляет средство, помогающее создать соответствующий код базы данных для классов. Этот подход называется разработкой Code First. Рассмотрим следующий класс Product для примера приложения витрины, которое мы хотим хранить в реляционной базе данных, например Microsoft SQL Server.

У продукта есть первичный ключ и три дополнительных поля, которые будут созданы в базе данных:

  • EF будет определять свойство Id как первичный ключ по соглашению.
  • Name будет храниться в столбце, настроенном для хранения текста. Атрибут [Required] , дополняющий это свойство, добавит ограничение not null , чтобы обеспечить соблюдение объявленного поведения свойства.
  • Description будет храниться в столбце, настроенном для хранения текста, и имеет максимальную длину в 4000 символов в соответствии с атрибутом [MaxLength] . Схема базы данных будет настроена с помощью столбца с именем MaxLength с использованием типа данных varchar(4000) .
  • Свойство Price будет храниться как валюта. Атрибут [Range] создаст соответствующие ограничения, чтобы предотвратить хранение данных за пределами минимального и максимального объявленного значения.

Нам нужно добавить этот класс Product в класс контекста базы данных, который определяет операции подключения и преобразования в нашей базе данных.

Класс MyDbContext предоставляет одно свойство, определяющее доступ и преобразование для класса Product . Приложение настраивает этот класс для взаимодействия с базой данных, используя следующие записи в методе ConfigureServices класса Startup :

Приведенный выше код будет подключаться к базе данных SQL Server с указанной строкой подключения. Строку подключения можно поместить в файл appsettings.json, переменные среды или другие места хранения конфигурации и соответствующим образом заменить эту внедренную строку.

Затем можно создать таблицу базы данных, подходящую для этого класса, с помощью следующих команд:

Первая команда определяет изменения, внесенные в схему базы данных, в качестве новой миграции EF Create Product table . Миграция определяет способ применения и удаления новых изменений базы данных.

После применения вы получите простую таблицу Product в базе данных и некоторые новые классы, добавленные в проект и помогающие управлять схемой базы данных. Созданные классы по умолчанию можно найти в новой папке с именем Migrations. При внесении изменений в класс Product или добавлении дополнительных связанных классов, которые будут взаимодействовать с базой данных, необходимо снова выполнить команды с новым именем миграции. Эта команда создаст другой набор классов миграции для обновления схемы базы данных.

EF Database First

Предыдущая команда подключается к базе данных, используя указанную строку соединения и поставщик Microsoft.EntityFrameworkCore.SqlServer . После подключения создается класс контекста базы данных с именем MyDbContext . Кроме того, создаются вспомогательные классы для таблиц Product и Customer , которые были указаны с помощью параметров -t . Существует множество параметров конфигурации этой команды для создания иерархии классов, подходящей для вашей базы данных. Полный справочник см. в документации по команде.

Дополнительные сведения о EF Core можно найти на сайте "Документация Майкрософт".

Взаимодействие с веб-службами

Читайте также: