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

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

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

Начать курс

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

В мире C++ работа с базами данных исторически была более низкоуровневой, чем в языках вроде Python или Java. Однако современные проекты требуют удобства и продуктивности, поэтому разработчики всё чаще обращаются к ORM (Object-Relational Mapping). ORM для C++ позволяет работать с таблицами как с обычными C++ объектами, автоматически генерировать SQL-запросы и управлять миграциями схемы. В этой статье мы рассмотрим пять популярных библиотек: ODB, SQLiteCpp, SOCI, cppdb и sqlpp11, сравним их особенности и приведём практические примеры.

1. ODB — корпоративный стандарт

ODB — это мощный ORM-фреймворк для C++, который поддерживает множество СУБД: MySQL, PostgreSQL, SQLite, Oracle, SQL Server. Основная особенность — кодогенерация: вы описываете модель в заголовочном файле с аннотациями, а компилятор ODB (odb) создаёт код для работы с БД.

// person.hxx
#pragma once
#include <string>
#include <odb/core.hxx>

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

    const std::string& getName() const { return name_; }
    int getAge() const { return age_; }

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

После запуска odb -d mysql person.hxx генерируются файлы с реализацией. Далее используем стандартный паттерн:

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

int main() {
    auto db = std::make_shared<odb::mysql::database>("user", "pass", "mydb");
    Person p("Alice", 30);
    db->persist(p);
    // Загрузка
    auto loaded = db->load<Person>(1);
    return 0;
}

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

2. SQLiteCpp — лёгкость и простота

SQLiteCpp — это обёртка над SQLite3 в стиле C++ RAII. Не является полноценным ORM, но предоставляет удобный интерфейс для работы с запросами.

#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>

int main() {
    SQLite::Database db("test.db", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
    db.exec("CREATE TABLE IF NOT EXISTS person (id INTEGER PRIMARY KEY, name TEXT, age INT)");
    
    SQLite::Statement insert(db, "INSERT INTO person (name, age) VALUES (?, ?)");
    insert.bind(1, "Bob");
    insert.bind(2, 25);
    insert.exec();
    
    // Чтение
    SQLite::Statement query(db, "SELECT * FROM person WHERE age > ?");
    query.bind(1, 20);
    while (query.executeStep()) {
        std::cout << query.getColumn(1) << " " << query.getColumn(2) << "\n";
    }
    return 0;
}

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

3. SOCI — универсальный абстрактор

SOCI (The C++ Database Access Library) — это не ORM в чистом виде, а абстракция над разными СУБД (SQLite, PostgreSQL, MySQL, Oracle). Предоставляет удобный синтаксис для выполнения запросов и связывания результатов с C++ структурами.

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

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

int main() {
    soci::session sql(soci::sqlite3, "test.db");
    sql << "CREATE TABLE person (id INTEGER PRIMARY KEY, name TEXT, age INT)";
    
    Person p{1, "Charlie", 35};
    sql << "INSERT INTO person (id, name, age) VALUES (:id, :name, :age)",
        soci::use(p.id), soci::use(p.name), soci::use(p.age);
    
    // Чтение с маппингом
    Person loaded;
    sql << "SELECT id, name, age FROM person WHERE id = :id",
        soci::into(loaded.id), soci::into(loaded.name), soci::into(loaded.age),
        soci::use(1);
    return 0;
}

Плюсы: кроссплатформенность, поддержка нескольких СУБД, простота интеграции. Мину

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