orm-odb(c++),一种对象关系映射数据操作方式

基于ORM机制的C++数据库操作开源库ODB

最近在项目里遇到一个问题,关于数据库读取大量数据的,这部分代码项目里的思路是,对数据表做索引,然后依据索引排序,取出最上面的max_size(5000)条数据,然后基于后面的数据继续排序,取出最上面max_size(5000)条,依此循环直到取出最后一条数据. 开始我觉得这样可能效率会比较低,因为每次操作都要进行一次排序,我觉得用limit 0,max_size .limit 0+max_size,max_size+max_size这样的方法要快一些,后来想了一下问题的关键应该是在每次取第一条数据的时候,比如先排序再去取的话,因为建立了索引,所以排序是很快的,而且第一条马上就找到了,但是用limit 0,max_size这样的方法的话,每次查找第一条数据都要顺序数到位置,所以先排序再取数据的方法是稍微好一点的.


不过正是因为这个问题,偶然发现了一个c++的数据库操作库,基于ORM机制,google了一下ORM,全称是对象关系映射(Object Relational Mapping),简单来说就是使用这个库可以让程序员避免直接操作sql语句,数据的存储和对象直接相关,多说无益,记下使用方法以便日后用得到.


我是在windows平台上编译和测试的.这里记下windows下的使用方法:
首先从http://www.codesynthesis.com/products/odb/ 下载到源码,主要是the Common Runtime Library和the Database Runtime Library,前者是ODB的基本库,后者是基于不同数据库的扩展库,后者要基于前者.我用的是mysql,所以要下载mysql的扩展库.前者没有任何依赖可以直接编译,后者要基于前者和mysql的库,我编译的时候总是不成功,后来发现我机器上安装的mysql是64位的,编译ODB的时候把win32改成X64后编译通过,以后要注意下这个问题.使用编译好的库启动官方的例子程序”hello”,一切正常.
简单的用法如下:

这是一个简单的person类.
// person.hxx

#include <string>

class person
{
public:
  person (const std::string& first,
          const std::string& last,
          unsigned short age);

  const std::string& first () const;
  const std::string& last () const;

  unsigned short age () const;
  void age (unsigned short);

private:
  std::string first_;
  std::string last_;
  unsigned short age_;
};

使用ODB后修改如下:

// person.hxx

#include <string>

#include <odb/core.hxx>     // (1)

#pragma db object           // (2)
class person
{
  ...

private:
  person () {}              // (3)

  friend class odb::access; // (4)

  #pragma db id auto        // (5)
  unsigned long id_;        // (5)

  std::string first_;
  std::string last_;
  unsigned short age_;
};

使用这个sql文件建立数据表
//This file was generated by ODB, object-relational mapping (ORM) compiler for C++.

DROP TABLE IF EXISTS `person`;

CREATE TABLE `person` (
  `id` BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `first` TEXT NOT NULL,
  `last` TEXT NOT NULL,
  `age` SMALLINT UNSIGNED NOT NULL)
 ENGINE=InnoDB;

测试例子如下,执行commit函数后三个person类对象的数据就写入了数据库中,真的非常方便简洁.
//driver.cxx

#include <memory>   // std::auto_ptr
#include <iostream>

#include <odb/database.hxx>
#include <odb/transaction.hxx>

#include <odb/mysql/database.hxx>

#include "person.hxx"
#include "person-odb.hxx"

using namespace std;
using namespace odb::core;

int
main (int argc, char* argv[])
{
  try
  {
    //auto_ptr<database> db (new odb::mysql::database (argc, argv));
    auto_ptr<database> db (new odb::mysql::database("dll","dll","odb_test","localhost",3306));
    unsigned long john_id, jane_id, joe_id;

    // Create a few persistent person objects.
    //
    {
      person john ("John", "Doe", 33);
      person jane ("Jane", "Doe", 32);
      person joe ("Joe", "Dirt", 30);

      transaction t (db->begin ());

      // Make objects persistent and save their ids for later use.
      //
      john_id = db->persist (john);
      jane_id = db->persist (jane);
      joe_id = db->persist (joe);

      t.commit ();
    }
  }
  catch (const odb::exception& e)
  {
    cerr << e.what () << endl;
    return 1;
  }
}

这是ODB官方自带的例子,我们在使用ODB的时候需要自己生成person类的C++文件,使用官方的ODB Compiler,下载后将ODB的bin目录添加到系统的环境变量中,通过person.hxx文件即可得到ODB需要的其他c++文件,类似protobuf的使用.
odb -d mysql –generate-query –generate-schema person.hxx
这条命令即可生成person-odb.hxx, person-odb.ixx, person-odb.cxx这三个文件,这样配合编译好的库文件就可以操作数据库了.