ActiveRecord

ActiveRecord (AR) — шаблон проектирования приложений, описанный Мартином Фаулером в книге Patterns of Enterprise Application Architecture («Шаблоны архитектуры корпоративных приложений»). ActiveRecord является популярным способом доступа к данным реляционных баз данных в объектно-ориентированном программировании.

Схема ActiveRecord — это подход к доступу к данным в базе данных. Таблица базы данных или представление обёрнуты в классы. Таким образом, объектный экземпляр привязан к единственной строке в таблице. После создания объекта новая строка будет добавляться к таблице на сохранение. Любой загруженный объект получает свою информацию от базы данных. Когда объект обновлён, соответствующая строка в таблице также будет обновлена. Класс-обёртка реализует методы средства доступа или свойства для каждого столбца в таблице или представлении.

Этот образец обычно используется объектными инструментами персистентности и в объектно-реляционном отображении (ORM). Как правило, отношения внешнего ключа будут представлены как объектный экземпляр надлежащего типа через свойство.

Реализации данного шаблона часто нарушают принцип единственной ответственности (SRP), совмещая в одном объекте как представление и внутреннюю логику самого объекта, так и механизмы CRUD, поэтому ActiveRecord может считаться антипаттерном[1]. В других случаях это утверждение спорно, так как сам по себе объект, реализующий ActiveRecord, не содержащий никакой бизнес-логики, а предоставляющий таблицу из базы данных, имеет лишь одну причину для изменения (изменение таблицы), что не противоречит определению принципа SRP[2].

Общий принцип работы ActiveRecord

Пусть существует таблица в базе данных. Для данной таблицы создаётся специальный класс ActiveRecord, являющийся отражением (представлением) таблицы, таким образом, что:

  • каждый экземпляр данного класса соответствует одной записи таблицы;
  • при создании нового экземпляра класса (и заполнении соответствующих полей) в таблицу добавляется новая запись;
  • при чтении полей объекта считываются соответствующие значения записи таблицы баз данных;
  • при изменении (удалении) какого-либо объекта изменяется (удаляется) соответствующая ему запись.

Реализация

Реализация концепции ActiveRecord существует во многих средах разработки для различных языков программирования. Например, если в базе данных есть таблица parts с полями name (тип string) и price (тип number), и шаблон ActiveRecord реализован в классе Part, то следующий псевдокод:

part = new Part()
part.name = "Sample part"
part.price = 123.45
part.save()

создаст новую запись в таблице parts с данными значениями, и будет примерно соответствовать команде SQL

INSERT INTO parts (name, price) VALUES ('Sample part', 123.45);

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

b = Part.find_first("name", "gearbox")

Этот код создаст новый экземпляр класса Part, основанный на данных первой найденной записи в таблице parts, у которой поле name равно «gearbox».

Команда SQL может быть подобна одной из показанных ниже, в зависимости от реализации SQL в конкретной базе данных:

SELECT * FROM parts WHERE name = 'gearbox' LIMIT 1; -- MySQL или PostgreSQL

или

SELECT * FROM parts WHERE name = 'gearbox' and rownum < 2; -- Oracle

или

SELECT TOP 1 * FROM parts WHERE name = 'gearbox'; -- Microsoft SQL Server

Ниже представлены популярные реализации шаблона в различных языках программирования и фреймворках[3].

Ruby

  • Active Record в составе Ruby on Rails — наиболее известная и каноническая реализация шаблона, выполняющая роль модельного слоя (M в MVC)[4][5]. Ключевыми особенностями являются принцип «соглашение вместо конфигурации», интуитивно понятные CRUD-операции, система миграций для управления схемой базы данных и декларативное описание связей между моделями[6][7]. Active Record остается «сердцем» Rails. В последних версиях (включая Rails 7.2 и выше) разработчики сфокусированы на улучшении производительности, нативной поддержке GitHub CI по умолчанию и расширении возможностей работы с типами данных[8][9].

PHP

  • Eloquent ORM во фреймворке Laravel — популярная реализация, где каждая таблица базы данных имеет соответствующую «модель» для взаимодействия[10][11]. Поддерживает автоматическое ведение временных меток created_at и updated_at[12].
  • Active Record во фреймворке Yii — мощная реализация с поддержкой широкого спектра реляционных СУБД (MySQL, PostgreSQL, SQLite, MS SQL, Oracle)[13]. Позволяет использовать «ленивую» (lazy) и «жадную» (eager) загрузку связанных данных для оптимизации запросов[14].
  • Следует отметить, что класс ActiveRecord во фреймворке CodeIgniter является конструктором запросов к базе данных, а не реализацией шаблона ActiveRecord.

JavaScript / TypeScript (Node.js)

  • TypeORM — одна из наиболее популярных ORM для Node.js, которая поддерживает как шаблон ActiveRecord, так и Data Mapper[15]. При использовании ActiveRecord модель наследуется от класса BaseEntity и получает методы для работы с базой данных (save(), remove(), find()).

Python В экосистеме Python доминирующие ORM, такие как в Django и SQLAlchemy, реализуют шаблон Data Mapper, хотя и имеют некоторые черты ActiveRecord[16]. Однако существуют и прямые реализации:

  • Orator ORM — реализация, синтаксически близкая к Eloquent из Laravel[17].
  • Peewee — легковесная ORM, которую можно использовать в стиле ActiveRecord[18].
  • Существуют и другие библиотеки, например, pyactiverecord[19].

Java Как и в Python, основные технологии доступа к данным, такие как JPA и Hibernate, основаны на шаблоне Data Mapper. Тем не менее, существуют библиотеки, реализующие ActiveRecord:

  • ActiveJDBC — легковесная ORM, вдохновлённая реализацией из Ruby on Rails, которая минимизирует конфигурацию за счёт анализа схемы базы данных[20].
  • ActiveJpa — библиотека, реализующая паттерн ActiveRecord поверх стандартного JPA[21].
  • jOOQ — инструмент для построения SQL-запросов, который также может генерировать классы, реализующие ActiveRecord-подобный паттерн.

C# / .NET В экосистеме .NET стандартной ORM является Entity Framework Core, которая реализует шаблон Data Mapper[22]. Исторически существовал проект Castle ActiveRecord, построенный на основе NHibernate и предоставлявший слой ActiveRecord, но он утратил популярность с развитием Entity Framework.

Примечания

Ссылки