Hiberlite

Hiberliteは「C++向けのSQLite ORM」として開発された、信頼性の高いデータストレージとACIDトランザクション、シンプルなランダムアクセスを必要とし、SQL でのコーディングを好まない開発者のためのライブラリです。従来のSQLシリアライザーとは異なり、HiberliteでマップされたC++オブジェクトはActive Recordパターンのように振る舞い、「全データを読み取り/一部を変更/全てを書き戻し」という制約から解放されます。Boost.SerializationにインスパイアされたAPIにより、学習するAPIがほとんどなく直感的な使用が可能です。

ORMC++SQLiteActive Recordシリアライゼーション

GitHub概要

paulftw/hiberlite

C++ ORM for SQLite

スター721
ウォッチ62
フォーク120
作成日:2011年9月11日
言語:C++
ライセンス:BSD 3-Clause "New" or "Revised" License

トピックス

なし

スター履歴

paulftw/hiberlite Star History
データ取得日時: 2025/7/17 07:02

ライブラリ

Hiberlite

概要

Hiberliteは「C++向けのSQLite ORM」として開発された、信頼性の高いデータストレージとACIDトランザクション、シンプルなランダムアクセスを必要とし、SQL でのコーディングを好まない開発者のためのライブラリです。従来のSQLシリアライザーとは異なり、HiberliteでマップされたC++オブジェクトはActive Recordパターンのように振る舞い、「全データを読み取り/一部を変更/全てを書き戻し」という制約から解放されます。Boost.SerializationにインスパイアされたAPIにより、学習するAPIがほとんどなく直感的な使用が可能です。

詳細

Hiberlite 2025年版はC++ SQLite ORMの軽量ソリューションとして、自動スキーマ生成、スマートポインタ管理、内部主キー自動生成など現代的なC++開発に必要な機能を提供しています。データベーススキーマは単純にデータベースに格納されるクラスのセットとして定義され、Hiberliteが必要なテーブルとカラムを決定します。bean_ptrスマートポインタはboost::shared_ptrにインスパイアされ、参照されなくなったオブジェクトの自動保存を保証します。Active Recordパターンによりオブジェクト操作が直感的で、複雑なリレーションシップ処理も簡素化されています。

主な特徴

  • Active Recordパターン: オブジェクトがデータベース操作を直接実行
  • 自動スキーマ生成: クラス定義からテーブル構造を自動推論
  • スマートポインタ: bean_ptrによる自動メモリ・永続化管理
  • 内部主キー自動生成: 各オブジェクトに対する透明な主キー管理
  • SQLシリアライゼーション: Boost.SerializationライクなシンプルなAPI
  • 依存関係フリー: サードパーティライブラリに依存しない軽量設計

メリット・デメリット

メリット

  • 学習コストが非常に低く、APIがシンプルで直感的
  • Boost.Serializationに馴染みがある開発者には習得が容易
  • Active Recordパターンによりオブジェクト指向的な操作が可能
  • 設定ファイルやXMLが不要で、アノテーションも最小限
  • 軽量でサードパーティ依存関係がない
  • 自動スキーマ管理によりDDL操作が不要

デメリット

  • 大規模なプロジェクトではスケーラビリティに制約がある
  • データのサブセット取得方法が不明瞭で、標準的でない可能性
  • 完全に成熟していない可能性があり、プロダクションレディか要検証
  • 複雑なクエリやパフォーマンス最適化には制限がある
  • コミュニティとドキュメントが限定的
  • 現代的なC++機能(C++14以降)への対応が不明

参考ページ

書き方の例

セットアップ

# GitHubからクローン
git clone https://github.com/paulftw/hiberlite.git

# プロジェクトに統合(src/以下の全ファイルをコンパイル・リンク)
# CMakeLists.txt例
add_subdirectory(hiberlite)
target_link_libraries(your_project hiberlite sqlite3)
// 基本インクルード
#include "hiberlite.h"

基本的な使い方

// クラスの準備
class MyClass {
    friend class hiberlite::access;
    template<class Archive>
    void hibernate(Archive & ar) {
        ar & HIBERLITE_NVP(a);
        ar & HIBERLITE_NVP(b);
        ar & HIBERLITE_NVP(vs);
    }
    
public:
    int a;
    double b;
    std::vector<std::string> vs;
    
    MyClass() : a(0), b(0.0) {}
    MyClass(int a_val, double b_val) : a(a_val), b(b_val) {}
};

// クラスのエクスポート(必須)
HIBERLITE_EXPORT_CLASS(MyClass)

// より複雑なクラス例
class Person {
    friend class hiberlite::access;
    template<class Archive>
    void hibernate(Archive & ar) {
        ar & HIBERLITE_NVP(name);
        ar & HIBERLITE_NVP(age);
        ar & HIBERLITE_NVP(email);
        ar & HIBERLITE_NVP(addresses);
    }
    
public:
    std::string name;
    int age;
    std::string email;
    std::vector<std::string> addresses;
    
    Person() : age(0) {}
    Person(const std::string& n, int a, const std::string& e) 
        : name(n), age(a), email(e) {}
};

HIBERLITE_EXPORT_CLASS(Person)

クエリ実行

#include <iostream>

// データベースの初期化と使用
void demonstrateBasicUsage() {
    // データベース初期化
    hiberlite::Database db("example.db");
    db.registerBeanClass<MyClass>();
    db.registerBeanClass<Person>();
    
    // オブジェクトの作成と保存(方法1: copyBean)
    MyClass x;
    x.a = 42;
    x.b = 3.14159;
    x.vs.push_back("hello");
    x.vs.push_back("world");
    
    hiberlite::bean_ptr<MyClass> p1 = db.copyBean(x);
    std::cout << "Saved MyClass with ID: " << p1.get_id() << std::endl;
    
    // オブジェクトの作成と保存(方法2: createBean)
    hiberlite::bean_ptr<Person> person = db.createBean<Person>();
    person->name = "田中太郎";
    person->age = 30;
    person->email = "[email protected]";
    person->addresses.push_back("東京都渋谷区");
    person->addresses.push_back("大阪府大阪市");
    
    std::cout << "Saved Person with ID: " << person.get_id() << std::endl;
}

// より複雑な使用例
void demonstrateAdvancedUsage() {
    hiberlite::Database db("advanced.db");
    db.registerBeanClass<Person>();
    
    // 複数オブジェクトの作成
    std::vector<hiberlite::bean_ptr<Person>> people;
    
    for (int i = 0; i < 5; ++i) {
        hiberlite::bean_ptr<Person> p = db.createBean<Person>();
        p->name = "Person" + std::to_string(i);
        p->age = 20 + i * 5;
        p->email = "person" + std::to_string(i) + "@example.com";
        p->addresses.push_back("Address " + std::to_string(i));
        
        people.push_back(p);
    }
    
    std::cout << "Created " << people.size() << " people" << std::endl;
    
    // オブジェクトの変更(自動保存)
    people[0]->age = 99;
    people[0]->email = "[email protected]";
    // bean_ptrのスコープから外れると自動的にデータベースに保存される
}

データ操作

// 複雑なデータ構造の例
class UserAccount {
    friend class hiberlite::access;
    template<class Archive>
    void hibernate(Archive & ar) {
        ar & HIBERLITE_NVP(username);
        ar & HIBERLITE_NVP(password_hash);
        ar & HIBERLITE_NVP(profile);
        ar & HIBERLITE_NVP(settings);
        ar & HIBERLITE_NVP(friends);
    }
    
public:
    std::string username;
    std::string password_hash;
    std::map<std::string, std::string> profile;
    std::map<std::string, bool> settings;
    std::vector<std::string> friends;
    
    UserAccount() {}
    UserAccount(const std::string& user) : username(user) {}
};

HIBERLITE_EXPORT_CLASS(UserAccount)

// 使用例
void demonstrateComplexData() {
    hiberlite::Database db("users.db");
    db.registerBeanClass<UserAccount>();
    
    // ユーザーアカウントの作成
    hiberlite::bean_ptr<UserAccount> user = db.createBean<UserAccount>();
    user->username = "testuser";
    user->password_hash = "hashed_password_123";
    
    // プロフィール情報の設定
    user->profile["first_name"] = "太郎";
    user->profile["last_name"] = "田中";
    user->profile["bio"] = "ソフトウェア開発者";
    user->profile["location"] = "東京";
    
    // 設定の管理
    user->settings["email_notifications"] = true;
    user->settings["dark_mode"] = false;
    user->settings["auto_save"] = true;
    
    // フレンドリストの管理
    user->friends.push_back("friend1");
    user->friends.push_back("friend2");
    user->friends.push_back("friend3");
    
    std::cout << "User " << user->username << " created with " 
              << user->friends.size() << " friends" << std::endl;
}

設定とカスタマイズ

// 高度なクラス設計の例
class BlogPost {
    friend class hiberlite::access;
    template<class Archive>
    void hibernate(Archive & ar) {
        ar & HIBERLITE_NVP(title);
        ar & HIBERLITE_NVP(content);
        ar & HIBERLITE_NVP(author);
        ar & HIBERLITE_NVP(tags);
        ar & HIBERLITE_NVP(created_at);
        ar & HIBERLITE_NVP(updated_at);
        ar & HIBERLITE_NVP(published);
        ar & HIBERLITE_NVP(view_count);
    }
    
public:
    std::string title;
    std::string content;
    std::string author;
    std::vector<std::string> tags;
    std::string created_at;  // 簡易的にstring使用
    std::string updated_at;
    bool published;
    int view_count;
    
    BlogPost() : published(false), view_count(0) {
        // 現在時刻を設定(簡易版)
        created_at = "2025-01-01 00:00:00";
        updated_at = created_at;
    }
    
    void updateContent(const std::string& new_content) {
        content = new_content;
        updated_at = "2025-01-01 12:00:00"; // 実際は現在時刻
    }
    
    void addTag(const std::string& tag) {
        tags.push_back(tag);
    }
    
    void publish() {
        published = true;
        updated_at = "2025-01-01 15:00:00";
    }
    
    void incrementView() {
        view_count++;
    }
};

HIBERLITE_EXPORT_CLASS(BlogPost)

// ブログシステムの実装例
class BlogManager {
private:
    hiberlite::Database db;
    
public:
    BlogManager(const std::string& db_path) : db(db_path) {
        db.registerBeanClass<BlogPost>();
        db.registerBeanClass<UserAccount>();
    }
    
    hiberlite::bean_ptr<BlogPost> createPost(const std::string& title, 
                                           const std::string& content,
                                           const std::string& author) {
        hiberlite::bean_ptr<BlogPost> post = db.createBean<BlogPost>();
        post->title = title;
        post->content = content;
        post->author = author;
        return post;
    }
    
    void publishPost(hiberlite::bean_ptr<BlogPost> post) {
        post->publish();
        // bean_ptrによる自動保存
    }
    
    void viewPost(hiberlite::bean_ptr<BlogPost> post) {
        post->incrementView();
        // 変更は自動的に保存される
    }
};

エラーハンドリング

#include <stdexcept>

// エラーハンドリングの例
class SafeDatabaseManager {
private:
    std::unique_ptr<hiberlite::Database> db;
    bool initialized;
    
public:
    SafeDatabaseManager() : initialized(false) {}
    
    bool initialize(const std::string& db_path) {
        try {
            db = std::make_unique<hiberlite::Database>(db_path);
            db->registerBeanClass<Person>();
            db->registerBeanClass<BlogPost>();
            initialized = true;
            return true;
        } catch (const std::exception& e) {
            std::cerr << "Database initialization failed: " << e.what() << std::endl;
            initialized = false;
            return false;
        }
    }
    
    template<typename T>
    hiberlite::bean_ptr<T> safeCreateBean() {
        if (!initialized) {
            throw std::runtime_error("Database not initialized");
        }
        
        try {
            return db->createBean<T>();
        } catch (const std::exception& e) {
            std::cerr << "Failed to create bean: " << e.what() << std::endl;
            throw;
        }
    }
    
    template<typename T>
    hiberlite::bean_ptr<T> safeCopyBean(const T& object) {
        if (!initialized) {
            throw std::runtime_error("Database not initialized");
        }
        
        try {
            return db->copyBean(object);
        } catch (const std::exception& e) {
            std::cerr << "Failed to copy bean: " << e.what() << std::endl;
            throw;
        }
    }
    
    bool isInitialized() const {
        return initialized;
    }
};

// 安全な使用例
void safeDatabaseUsage() {
    SafeDatabaseManager manager;
    
    if (!manager.initialize("safe_example.db")) {
        std::cerr << "Failed to initialize database" << std::endl;
        return;
    }
    
    try {
        // 安全なオブジェクト作成
        auto person = manager.safeCreateBean<Person>();
        person->name = "Safe User";
        person->age = 25;
        person->email = "[email protected]";
        
        std::cout << "Safely created person with ID: " << person.get_id() << std::endl;
        
        // 複製による保存
        Person temp_person("Copy User", 35, "[email protected]");
        auto copied_person = manager.safeCopyBean(temp_person);
        
        std::cout << "Safely copied person with ID: " << copied_person.get_id() << std::endl;
        
    } catch (const std::exception& e) {
        std::cerr << "Operation failed: " << e.what() << std::endl;
    }
}