ORM для C++: сравнение и примеры использования (ODB, SOCI, SQLiteCpp)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

ORM для C++: сравнение и примеры использования

В отличие от языков с динамической типизацией (Python, PHP), C++ не имеет встроенной поддержки рефлексии и метапрограммирования, достаточной для создания "магического" ORM. Тем не менее, существует несколько мощных решений, которые автоматизируют работу с базами данных. В этой статье мы сравним три популярные библиотеки: ODB, SOCI и SQLiteCpp, и приведём примеры их использования.

Критерии сравнения

При выборе ORM для C++ стоит обратить внимание на:

  • Тип генерации кода — внешний генератор или шаблоны C++.
  • Поддержка СУБД — SQLite, PostgreSQL, MySQL, Oracle.
  • Производительность — накладные расходы на отображение.
  • Сложность интеграции — требуется ли отдельный шаг сборки.

1. ODB — промышленный ORM для C++

ODB — это коммерческий (с бесплатной версией для open-source) ORM, основанный на генерации кода из аннотированных заголовочных файлов. Он поддерживает реляционные базы данных (SQLite, PostgreSQL, MySQL, Oracle) и даже NoSQL (MongoDB).

Пример с ODB (SQLite)

Сначала объявляем класс-сущность:

#include <odb/core.hxx>

#pragma db object
class Person {
public:
    Person(const std::string& name, int age)
        : name_(name), age_(age) {}

    unsigned long id() const { return id_; }
    const std::string& name() const { return name_; }
    int age() const { return age_; }

private:
    friend class odb::access;
    #pragma db id auto
    unsigned long id_;
    std::string name_;
    int age_;
};

Использование:

#include <odb/database.hxx>
#include <odb/sqlite/database.hxx>
#include <odb/transaction.hxx>
#include "person.hxx"
#include "person-odb.hxx"

int main() {
    auto db = std::make_shared<odb::sqlite::database>("test.db");
    odb::transaction t(db->begin());

    Person p("Alice", 30);
    db->persist(p); // INSERT

    auto result = db->query<Person>(
        odb::query<Person>::age > 25);
    for (const auto& person : result) {
        std::cout << person.name() << std::endl;
    }
    t.commit();
}

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

2. SOCI — легковесный "data access layer"

SOCI — это не полноценный ORM, а библиотека для работы с SQL из C++, которая предоставляет удобный синтаксис для выполнения запросов и отображения результатов. Она работает с SQLite, PostgreSQL, MySQL, Oracle и ODBC.

Пример с SOCI

#include <soci/soci.h>
#include <soci/sqlite3/soci-sqlite3.h>
#include <iostream>

struct Person {
    int id;
    std::string name;
    int age;
};

int main() {
    soci::session sql(soci::sqlite3, "test.db");
    sql << "CREATE TABLE IF NOT EXISTS person ("
           "id INTEGER PRIMARY KEY, "
           "name TEXT, age INTEGER)";

    // Вставка
    sql << "INSERT INTO person (name, age) VALUES (:name, :age)",
        soci::use("Bob"), soci::use(25);

    // Выборка с отображением в структуру
    Person p;
    soci::indicator ind;
    sql << "SELECT id, name, age FROM person WHERE id = :id",
        soci::use(1), soci::into(p.id), soci::into(p.name, ind), soci::into(p.age);

    if (ind == soci::i_ok) {
        std::cout << p.name << " " << p.age << std::endl;
    }
}

Плюсы: лёгкая интеграция, нет генерации кода, поддержка prepared statements. Минусы: нет автоматического отображения объектов, требуется писать SQL вручную.

3. SQLiteCpp — минималистичная обёртка для SQLite

SQLiteCpp — это header-only библиотека, предоставляющая C++ API для SQLite. Она не является ORM в полном смысле, но автоматизирует управление ресурсами и предоставляет удобные классы для работы с БД.

Пример с SQLiteCpp

#include <SQL                    

Рекомендаций