ORM para C++: comparação e exemplos de uso (ODB, SOCI, SQLiteCpp)

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

ORM para C++: comparação e exemplos de uso



Ao contrário de linguagens com tipagem dinâmica (Python, PHP), C++ não possui suporte embutido a reflexão e metaprogramação suficiente para criar uma ORM "mágica". No entanto, existem várias soluções poderosas que automatizam o trabalho com bancos de dados. Neste artigo, compararemos três bibliotecas populares: ODB, SOCI e SQLiteCpp, e forneceremos exemplos de seu uso.



Critérios de comparação

Ao escolher uma ORM para C++, vale a pena considerar:

  • Tipo de geração de código — gerador externo ou templates C++.
  • Suporte a SGBDs — SQLite, PostgreSQL, MySQL, Oracle.
  • Desempenho — sobrecarga do mapeamento.
  • Complexidade de integração — se é necessária uma etapa de compilação separada.


1. ODB — ORM industrial para C++

ODB é uma ORM comercial (com versão gratuita para open-source) baseada na geração de código a partir de arquivos de cabeçalho anotados. Ela suporta bancos de dados relacionais (SQLite, PostgreSQL, MySQL, Oracle) e até NoSQL (MongoDB).



Exemplo com ODB (SQLite)

Primeiro, declaramos a classe entidade:

#include <odb/core.hxx>

#pragma db objectclass 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_;};


Uso:

#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();}


Prós: modelo de objeto completo, suporte a relacionamentos, carregamento preguiçoso. Contras: precisa de um gerador de código (etapa de compilação), licença comercial.



2. SOCI — "data access layer" leve

SOCI não é uma ORM completa, mas uma biblioteca para trabalhar com SQL em C++ que fornece uma sintaxe conveniente para executar consultas e mapear resultados. Ela funciona com SQLite, PostgreSQL, MySQL, Oracle e ODBC.



Exemplo com 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)";

// Inserção sql << "INSERT INTO person (name, age) VALUES (:name, :age)", soci::use("Bob"), soci::use(25);

// Consulta com mapeamento para struct 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; }}


Prós: integração leve, sem geração de código, suporte a prepared statements. Contras: sem mapeamento automático de objetos.

Recommendations