ORM for C++: Comparison and Examples of Library Usage

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

ORM for C++: Comparison and Usage Examples



In modern C++ development, working with databases often requires a balance between performance and convenience. Unlike languages with a rich ORM ecosystem (such as Python or Java), C++ offers a narrower but mature selection of tools. In this article, we will compare four popular libraries: ODB, SQLiteCpp, Soci, and sqlpp11. We will examine their architecture, syntax, performance, and code examples.



1. ODB — The Industry Standard

ODB is a full-featured ORM compiler for C++. It generates code from header files, supports relational databases (MySQL, PostgreSQL, SQLite, Oracle), and provides powerful object-relational mapping.



Key Features:

  • Automatic code generation via a precompiler (odb)
  • Support for inheritance, polymorphism, and STL containers
  • Lazy loading, caching, transactions


Example: Model and Query

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

#pragma db objectclass Person {public: Person() = default; Person(const std::string& name, int age) : name_(name), age_(age) {}

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_;};


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

int main() { auto db = std::make_shared<odb::sqlite::database>("test.db"); // Insert Person p("Alice", 30); db->persist(p); // Query using query = odb::query<Person>; auto result = db->query<Person>(query::age > 25); for (const auto& person : result) { std::cout << person.name() << ""; } return 0;}


2. SQLiteCpp — Lightweight Wrapper

SQLiteCpp is a minimalist C++ wrapper over the SQLite C API. It is not a full ORM, but it provides a convenient RAII interface for working with SQL queries.



Key Features:

  • Dependency only on SQLite3
  • Simple API: Database, Statement, Transaction
  • Support for prepared statements and parameter binding


Example: Insert and Select

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

int main() { SQLite::Database db("test.db", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); // Create table db.exec("CREATE TABLE IF NOT EXISTS person (id INTEGER PRIMARY KEY, name TEXT, age INT)"); // Insert with parameters SQLite::Statement insert(db, "INSERT INTO person (name, age) VALUES (?, ?)"); insert.bind(1, "Bob"); insert.bind(2, 25); insert.exec(); // Select SQLite::Statement query(db, "SELECT name, age FROM person WHERE age > ?"); query.bind(1, 20); while (query.executeStep()) { std::cout << query.getColumn(0).getText() << " - " << query.getColumn(1).getInt() << ""; } return 0;}


3. Soci — Universal Database Access

Soci is a library for working with various databases (MySQL, PostgreSQL, SQLite, Oracle) through a unified interface. It provides both dynamic queries and support for ORM-like mapping.



Key Features:

  • Support for multiple backends via plugins
  • Parameter binding using the << operator and into()
  • Support for transactions and bulk operations


Example: Working with Queries


                
    
    

Recommendations