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.
Também na biblioteca
Monitoramento de aplicações Rust: biblioteca `tracing`
Trabalho com imagens em Swift: redimensionamento e corte para iOS/macOS
Validação de dados em Java: visão geral de ferramentas e bibliotecas
Trabalhando com XML em Rust: bibliotecas quick-xml, roxmltree e serde_xml_rs