C++ ORM ODB入门
1.ORM
ORM, Object Relational Mapping, 对象关系映射,用来将基于对象的数据结构映射到SQL的数据结构中。即将基于对象的数据映射到关系表中的字段,然后我们可以通过对象提供的接口来操作数据库,而无需写sql语句来操作数据库。
一般一张关系表对应两个类,一个实体类和一个操作类。
ORM是一种框架,而不是一种实现。
2.C++ 的ORM的实现ODB
1)一个简单的例子
#include <odb/core.hxx> //(1)
#pragma db object//(2)
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:
person(); //(3)
friend class odb::access;//(4)
#pragma db id auto//(5)
unsigned long id_;//(5)
std::string first_;
std::string email_;
std::string last_;
unsigned short age_;
};
Note:
(1) headers to provide class like 'access'
(2) 告诉编译器这是一个persistent class,所以我们要将#pragma db object放在类的定义前。将一个类声明为persistent class并不意味着这个类的所有对象都会被存储到数据库中。
(3)这个构造函数在实例化一个persistent class时会用到。
(4)让默认的构造函数和其它类成员能够访问access类。
(5)每个persistent object通常都要有一个独一无二的id.如果persistent object没有定义id,那么数据库的操作就会受限。
#pragma db id auto 用来指定这个对象id,auto表明这个id的值是有数据库自动分配的。
这个id可以使这个类本身就具有的成员,也可以是自己添加仅作为id来标识不同的persistent对象。上面的例子中的id_就是仅仅用来区别persistent object.
上面的例子我们也可以写成:
#include <odb/core.hxx> //(1)
#pragma db object//(2)
class person
{
public:
person();
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:
#pragma db id auto//(5)
unsigned long id_;//(5)
std::string first_;
std::string email_;
std::string last_;
unsigned short age_;
};
//用来指定persistent 的id
#pragma db object(person)
#pragma db member(person::email_) id
3.用ODB编译器生成代码
将上面的代码保存为person.hxx,然后使用如下的命令来编译:
odb -d mysql --generate-query person.hxx
-d 用来指定我们使用的数据库。odb支持很多不同的数据库,我们以mysql为例。
这个命令会让odb的编译器生成三个文件:person-odb.hxx, person-odb.ixx, person-odb.cxx.
--generate-query用来指定编译器生成数据库支持的代码。如果我们使用--generate-shema, 那么还将生成person-odb.sql文件。
ok, 现在我们已经有persistent class(person.cxx)和database support code(person-odb.hxx, person-odb.ixx, person-odb.cxx)了。
4.编译和运行
假如我们的main文件为diver.cxx, 我们应该先编译main文件和上面生成的cxx文件:
c++ -c driver.cxx
c++ -c person-odb.cxx -Iyou_dir_to_odb_headers
c++ -o driver driver.o person-odb.o -Lyou_dir_to_odb_lib
在运行数据库前,记得先启动mysql并在库中使用指定表格。
mysql --user=user_name --database=you_db\
5.一个更加实用的例子
// driver.cxx
//
#include <memory> // std::auto_ptr
#include <iostream>
#include <odb/database.hxx> //定义database类
#include <odb/transaction.hxx> //定义transaction类
#include <odb/mysql/database.hxx> //实现database类的接口,同样要include
#include "person.hxx"
#include "person-odb.hxx"
using namespace std;
using namespace odb::core;//relative namespace.下面直接使用odb::batabase和odb::transaction就可以了,不用写成odb::core::database和odb::core::transaction了。
int
main (int argc, char* argv[])
{
try
{
auto_ptr<database> db (new odb::mysql::database (argc, argv));//(1)
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 ());//(1)
// Make objects persistent and save their ids for later use.
//
john_id = db->persist (john);//(2)
jane_id = db->persist (jane);//(2)
joe_id = db->persist (joe);//(2)
t.commit ();//(3)
}
}
catch (const odb::exception& e)
{
cerr << e.what () << endl;
return 1;
}
}
Note:
(1) 首先,我们要先创建一个database对象和transaction对象。
odb的实现中,所有database的操作都必须在一个transaction内进行。transaction是我们操作数据库的工作量的一个原子单位。一个transaction内包含有很过个database操作。如果一次transaction成功,则这个transaction内的数据库操作都会成功。如果一次transaction失败,这个transaction内的所有操作都会失败。
(2)我们在new了很多person对象后,使用persist选择奖哪些对象存储到数据库。
(3)提交一次transaction。如果在commit之前程序崩溃,所有的将要进行保存的数据库都不会被存储。
编译程序,然后开启数据库,然后执行程序。查看SQL的记录,我们可看到如下记录:
INSERT INTO ‘person‘ (‘id‘,‘first‘,‘last‘,‘age‘) VALUES (?,?,?,?)
INSERT INTO ‘person‘ (‘id‘,‘first‘,‘last‘,‘age‘) VALUES (?,?,?,?)
INSERT INTO ‘person‘ (‘id‘,‘first‘,‘last‘,‘age‘) VALUES (?,?,?,?)
6.查询数据库
typedef odb::query<person> query;
typedef odb::result<person> result;
// Say hello to those over 30.
//
{
transaction t (db->begin ());
result r (db->query<person> (query::age > 30));
for (result::iterator i (r.begin ()); i != r.end (); ++i)
{
cout << "Hello, " << i->first () << "!" << endl;
}
t.commit ();
}
}
7.更新数据库
(1)//使用object id
unsigned long john_id, jane_id, joe_id;
// Create a few persistent person objects.
//
{
...
// Save object ids for later use.
//
john_id = john.id ();
jane_id = jane.id ();
joe_id = joe.id ();
}
// Joe Dirt just had a birthday, so update his age.
//
{
transaction t (db->begin ());
auto_ptr<person> joe (db->load<person> (joe_id));
joe->age (joe->age () + 1);
db->update (*joe);
t.commit ();
}
(2)不使用object id
// Joe Dirt just had a birthday, so update his age. An
// alternative implementation without using the object id.
//
{
transaction t (db->begin ());
result r (db->query<person> (query::first == "Joe" &&
query::last == "Dirt"));
result::iterator i (r.begin ());
if (i != r.end ())
{
auto_ptr<person> joe (i.load ());
joe->age (joe->age () + 1);
db->update (*joe);
}
t.commit ();
}
8.删除persistent object
删除一个object要使用到object 的id
// John Doe is no longer in our database.
//
{
transaction t (db->begin ());
db->erase<person> (john_id);
t.commit ();
}
当然,也可以不用object id
// John Doe is no longer in our database. An alternative
// implementation without using the object id.
//
{
transaction t (db->begin ());
result r (db->query<person> (query::first == "John" &&
query::last == "Doe"));
result::iterator i (r.begin ());
if (i != r.end ())
{
auto_ptr<person> john (i.load ());
db->erase (*john);
}
t.commit ();
}
C++ ORM ODB入门的更多相关文章
- C++ ORM ODB 入门介绍(二)
目录[-] 1. ODB中的继承类型 2. abstract和polymorphic的区别 3.polymorphic表格 4.早期版本如何实现polymorphic 5.实例 本节主要介绍ODB中的 ...
- C++ ORM ODB 入门(三)
本节介绍ODB的事务与 异常. 数据库操作经常涉及到操作多个表格,或者表格中的多行数据.因此必须保证整个过程是原子性的.ODB为数据库的事务提供了易于使用的接口. 使用odb::databse的相关方 ...
- C++ ORM ODB 入门介绍(一)
C++的语言特性决定了在C++中的ORM框架不可能像Java,C#那没有那么灵活. C++的ORM框架一般都是基于模板,编译时,因此其效率比起Java中的ORM框架更高. ODB是一个比较独立,成熟的 ...
- 19 Go的全能ORM简单入门
gorm 昨天我的ldap账户改了以后,openfalcon(v2.1)-dashboard竟然无法登陆了!显然,没有把我的密码同步到本地数据库里面,怎么办?只能改openfalcon用户认证的源码了 ...
- ORM:ODB安装使用过程
1.下载odb-2.4.0-i686-windows,是cpp和sql文件生成工具,已经编译好了,如果下odb-2.4.0估计是未编译好的这个项目: 2.将...\odb-2.4.0-i686 ...
- Java ORM Hibernate 入门笔记
一.下载 官网地址:http://hibernate.org/ Hibernate下有ORM(关系型数据库).OGM(NoSQL数据库).Search(对象全文检索).Validator的工具. OR ...
- PetaPoco轻量级ORM框架 - 入门安装
PetaPoco 是一个开源轻量级ORM,够小,够快,单文件 在GitHub上有很高的人气 1377星,几年来作者一直在更新 当前版本6.0.317 - Netstandard 2.0(同时支持.ne ...
- 数据持久层(三)ODB介绍
ODB: C++ Object-Relational Mapping (ORM) ODB is an open-source, cross-platform, and cross-database o ...
- Django学习笔记之ORM字段和字段参数
Object Relational Mapping(ORM) 一.ORM介绍 1. ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象 ...
随机推荐
- iOS 邓白氏编码的申请
http://www.cocoachina.com/ios/20161214/18225.html
- Android TableLayout 表格布局
TableLayout继承LinearLayout 有多少个TableRow对象就有多少行, 列数等于最多子控件的TableRow的列数 直接在TableLayout加控件,控件会占据一行 Table ...
- 《程序员代码面试指南》第二章 链表问题 将单链表每K个节点之间逆序
样例 链表1-2-3-4-5-6-7-8-9-10 K=3 ,结果 3-2-1-6-5-4-9-8-7-10 java代码 /** * @Description:将单链表每K个节点之间逆序 * @Au ...
- [原创]java WEB学习笔记05:Servlet中的ServletConfig对象
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- Delphi 的类型与指针
Delphi 的指针分为 "类型指针" 和 "无类型指针" 两类.Delphi 中的类型, 常用的也得有几百个, 我们可以给每种类型定义相应的类型指针.其实 D ...
- Codeforces Round #256 (Div. 2) E. Divisors 因子+dfs
E. Divisors time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...
- jquery实现自定义弹出框
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JQUERY Uploadify 3.1 C#使用案例
近来因为要做一个上传功能,而firefox又不能直接使用file这样的标签,所以试着用js来写了一个,结果发现代码太多,验证太复杂,而且效果也不理想. 相对的,jquery提供的这一套uploadif ...
- Git_学习_05_ 解决冲突
二.参考资料 1.使用git pull文件时和本地文件冲突怎么办? 2.git 冲突解决
- 201621123014《JAVA程序设计》第2周学习总结
1. 本周学习总结 引用数据类型:JAVA定义字符串实际上是创建字符串的引用,将引用指向需要的字符串. 字符串常量池:直接对引用赋值时,会先在字符串中搜索是否有这个对象,已有则不创建直接指向它. St ...