POCO Data User Guide

按Poco的文档,本文缩写、改编、注释POCO Data User Guide的内容,介绍Poco的数据库操作。原文见http://pocoproject.org/docs/00200-DataUserManual.html。

先介绍一个简单例子,无须解释,其意自明。

#include"Poco/Data/Common.h"#include"Poco/Data/SQLite/Connector.h"#includeusingnamespacePoco::Data;voidinit()

{

SQLite::Connector::registerConnector();

}voidshutdown()

{

SQLite::Connector::unregisterConnector();

}intmain(intargc,char*argv[])

{

init();

Session ses("SQLite","sample.db");intcount=0;

ses<

std::cout<

shutdown();

}

Session

表示与数据库的连接,每个Session有两个要素,一是Poco表示数据库种类的类型标识,二是连接每种数据库所需的一个字符串。注意,实际的软件中这两个参数一般不会硬编码在代码中。

以SQLite为例

Session ses("SQLite","sample.db");

Session ses(SessionFactory::instance()::create("SQLite","sample.db"));

读取和写入数据:占位符placeholder,use(),into()

写入操作中使用placeholder和use()

std::stringaName("Peter");

ses<

读取操作中使用placeholder和into()

std::stringaName;

ses<

也可以同时使用use()和into()

std::stringaName;

std::stringmatch("Peter")

ses<

poco_assert (aName==match);

一般情况下,数据表有多列,用如下形式

std::stringfirstName("Peter";

std::stringlastName("Junior");intage=0;

ses<

注意,placeholder与use或into的顺序是一一对应的。

Statement用于表示SQL语句

原型

templateStatement Session::operator<

两种赋值方式,第一种方式会立即执行语句

std::stringaName("Peter");

Statement stmt=( ses<

第二种赋值方式可以把语句保存起来,稍后再执行

std::stringaName("Peter");

Statement stmt=( ses<

stmt.execute();

poco_assert (stmt.done());

注意,包含占位符的语句只是一个字符串,Statement可以缓存起来,并可以稍后执行,再使用时可以复用一些语句,可以选择Statement的执行时机。于是有了所谓的predefined statement

Predefined Statement

所谓predefined statement即是句尾没有使用now的语句,如

Statement stmt=( ses<

用法如下

std::stringaName();

Statement stmt=( ses<

{

aName.append("x");

stmt.execute();

}

通过这样的操作,可以把一个复杂的算法用SQL语句实现,并包装成一个C++的函数,用数据库的操作完成大量的计算,这是一个非常有用的功能,比如上面的一段代码可以转化成函数形式

voidfoo(constvector&str)

{

std::stringaName();

Statement stmt=( ses<::const_iteartor it=str.begin(), e=str.end(); it!=e;++it)

{

aName.append(*it);

stmt.execute();

}

}

不愧为用C++封的数据操作,与C++代码几乎无缝连接,下面讲到使用C++的容器类型时,这种特征更加明显。

说明:

use()的输入参数是一个引用,而不可以是一个常量,下面的代码是错的

Statement stmt=(ses<

对容器类型的支持

如果与操作DB是使用容器类型,Poco要求对放入容器中的类型具有如下的要求

vector: no requirements

set: the < operator must be supported by the datatype. Note that duplicate key/value pairs are ignored.

multiset: the < operator must be supported by the datatype

map: the () operator must be supported by the datatype and return the key of the object. Note that duplicate key/value pairs are ignored.

multimap: the () operator must be supported by the datatype and return the key of the object

用容器类接收或是导出数据的例子如下:

std::stringaName("");

std::vector<:string>data;for(inti=0; i<100;++i)

{

aName.append("x");

data.push_back(aName);

}

ses<

导出数据的例子,注意,如果数据表中有多个表项,确用一个字符串接受,会抛出异常。

std::vector<:string> names;

ses << "SELECT NAME FROM FORENAME", into(names), now

The limit clause

数据库中的表项很多,具体取回多少表项用limit clause提定,共有四个limit, lowerLimit, upperLimit和rang

limit

std::vector<:string>names;

ses<

lowerLimit

std::stringaName;

ses<

upperLimit

std::stringaName;

Statement stmt=(ses<

stmt.execute();

range

std::stringaName;

Statement stmt=(ses<

stmt.execute();

将复杂数据结构映射成数据表

将对象转化成数据表,有两种思路,一是面向对象的数据库,即在数据库支持部分面向对象的操作,二是用编译语言实现对对象到数据表的映射,称为object relation map,即ORM,实现时关键时把变量名映射为数据表的字段名,所以ORM在脚本语言中比较容易实现,因为有些脚本语言有自反机制。

Poco实现了一种映射,虽不是特别优雅,但对C++来讲已经足够好了。思路是为每一个类实现一个存取类对象的模板,很类似于序列化操作。举例如下,如果类定义是

classPerson

{public://default constructor+destr.//getter and setter methods for all members[...]booloperator

}

Poco::UInt64operator()()const///we need this operator to return the key for the map and multimap{return_socialSecNr;

}private:

std::string_firstName;

std::string_lastName;

Poco::UInt64 _socialSecNr;

}

为了方便读写这个类对象,要实现一个类模板

namespacePoco {namespaceData {//类模板要放在Poco::Data中template<>classTypeHandler{public:staticstd::size_t size()

{return3;//we handle three columns of the Table!}staticvoidbind(std::size_t pos,constPerson&obj, AbstractBinder*pBinder)

{

poco_assert_dbg (pBinder!=0);//the table is defined as Person (FirstName VARCHAR(30), lastName VARCHAR, SocialSecNr INTEGER(3))//Note that we advance pos by the number of columns the datatype uses! For string/int this is one.TypeHandler<:string>::bind(pos++, obj.getFirstName(), pBinder);

TypeHandler<:string>::bind(pos++, obj.getLastName(), pBinder);

TypeHandler<:uint64>::bind(pos++, obj.getSocialSecNr(), pBinder);

}staticvoidprepare(std::size_t pos,constPerson&obj, AbstractPreparation*pPrepare)

{

poco_assert_dbg (pBinder!=0);//the table is defined as Person (FirstName VARCHAR(30), lastName VARCHAR, SocialSecNr INTEGER(3))//Note that we advance pos by the number of columns the datatype uses! For string/int this is one.TypeHandler<:string>::prepare(pos++, obj.getFirstName(), pPrepare);

TypeHandler<:string>::prepare(pos++, obj.getLastName(), pPrepare);

TypeHandler<:uint64>::prepare(pos++, obj.getSocialSecNr(), pPrepare);

}staticvoidextract(std::size_t pos, Person&obj,constPerson&defVal, AbstractExtractor*pExt)///obj will contain the result, defVal contains values we should use when one column is NULL{

poco_assert_dbg (pExt!=0);

std::stringfirstName;

std::stringlastName;

Poco::UInt64 socialSecNr=0;

TypeHandler<:string>::extract(pos++, firstName, defVal.getFirstName(), pExt);

TypeHandler<:string>::extract(pos++, lastName, defVal.getLastName(), pExt);

TypeHandler<:uint64>::extract(pos++, socialSecNr, defVal.getSocialSecNr(), pExt);

obj.setFirstName(firstName);

obj.setLastName(lastName);

obj.setSocialSecNr(socialSecNr);

}

};

} }//namespace Poco::Data

这个设计方案的好处在于,实现序列化的类不必干涉原有类的设计,缺点是依赖于字段在数据表中的相对位置,而数据库是建立在关系代数基础上的,并不重视这种位置(顺便提一句Wt中实现的映射则比这种实现方法好得多)。这种设计并不十分巧妙。

使用时如下:

std::map<:uint64 person>people;

ses<

RecordSet

从介绍中可以看出,这个是Poco::Data设计的一个核心类型,从中也可以猜出序列化具体类型时有可能就是用本类实现的。该类可以操纵数据库操作结果的结果,抽象为一个二维表(这是和数据库的概念有出入的,数据库的概念是集合,而不是二维表格,也就是说列之间是无序的,但RecordSet类依赖这种顺序)。

Statement select(session);

select<

select.execute();

RecordSet rs(select);boolmore=rs.moveFirst();while(more)

{for(std::size_t col=0; col

{

std::cout<()<

}

std::cout<<:endl>

more=rs.moveNext();

}

如果结合limit使用则如下

Statement select(session);

select<

RecordSet rs(select);while(!select.done())

{

select.execute();boolmore=rs.moveFirst();while(more)

{for(std::size_t col=0; col

{

std::cout<()<

}

std::cout<<:endl>

more=rs.moveNext();

}

}

Tuples

前面介绍了一个类对象如何序列化为数据库中的一组数据,是比较麻烦的,但利用Tuples就不那么麻烦了:

typedef Poco::Tuple<:string std::string>Person;

typedef std::vectorPeople;

People people;

people.push_back(Person("Bart Simpson","Springfield",12));

people.push_back(Person("Lisa Simpson","Springfield",10));

Statement insert(session);

insert<

Statement select(session);

select<

{

std::cout<get<0>()<get<1>()<get<2>()<<:endl>

}

从这个思路出发,可以设计一个存取对象的方法,这样C++的类定义与在数据库中的建表的工作就可以放在一起了,并可以保持一致

classPerson

{public:

typedef Poco::Tuple<:string std::string>PersonData;

Person(constPersonData&data)

{

_data=data;

}

Person(Session&session)

{

Statement select(session);

select<

Statement insert(session);

insert<

}private:

PersonData _data

};constmapPersonField={ {“Name”,0}, {“Address”,1}, {“Age”,2} };//最好在此外可以触发一个建立数据表的操作

Session Pooling

用于保存与数据库的连接,应用程序只起动少数几个连接,能重用时尽量重用,保存在SessionPool中,这样就把对一个数据库的访问(session)做为全局变量在整个应用程序中使用。

SessionPool pool("ODBC","...");//...Session sess(pool.get());

poco 连接mysql_[Poco]数据库操作简介相关推荐

  1. cyq.data 连接mysql_底层数据库操作类库CYQ.DATA查询

    单表查询: using (MAction action = new MAction("COMP","K3")) { //查询的字段 string colstr ...

  2. VBA连接SQL SERVER数据库操作Excel

     VBA连接SQL SERVER数据库操作Excel. Sub 按钮1_Click() Dim i As Integer, j As Integer, sht As Worksheet 'i,j为 ...

  3. Nginx 连接 Redis 实现数据库操作

    Nginx 连接 Redis 实现数据库操作 实现的功能:当有新的连接到达Nginx时,在redis记录连接数量. 1. redis 创建数据库 安装完成redis之后,通过set connums 0 ...

  4. idea连接sqlserver及数据库操作

    idea连接sqlserver及操作 一.在连接过程中遇到的问题: (1)数据库登录失败 (2)登录成功之后 数据库端口号怎么查看 二.代码连接数据库 ①加载驱动和连接数据库 三.数据库操作 连接详解 ...

  5. python连接sql sever_R和python连接SQL sever 数据库操作

    在R的使用中,为了方便提取数据, 我们经常要进行数据库进行操作,接下来我们尝试使用R进行连接数据. 这里我们使用R中的RODBC进行操作, 首先,我们需要先配置ODBC资源管理器 通过任务管理器或者w ...

  6. jedis连接mysql_使用Jedis操作Redis数据库

    Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Java的客户端,有Jedis.Redisson ...

  7. greendao连接mysql_使用GreenDao操作数据库

    大神们都说GreenDao性能最好,使用方便,最近在做一个项目,刚好用到操作本地数据库,so机缘巧合,开始学习GreenDao,顺便做一下笔记. (1)原理 我总有那么一个习惯,就是使用别人的工具,总 ...

  8. c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?

    一.MySQL 优点: 体积小.速度快.总体拥有成本低,开源: 支持多种操作系统: 是开源数据库,提供的接口支持多种语言连接操作 : MySQL的核心程序采用完全的多线程编程.线程是轻量级的进程,它可 ...

  9. thinkphp5.0连接mysql_thinkphp5.0数据库操作

    ThinkPHP数据库处理: 1.MySQL的数据库连接 首先配置database.php文件 使用{dump(config('database));}来查看数据库的配置项 使用 {$res = Db ...

  10. medoo连接mysql_Medoo PHP数据库操作类

    Medoo是一个加速网站开发的最轻量的PHP数据库框架类!Medoo可以极大地加快你的PHP项目的开发.在进行Web开发的时候,很大一部分企业或个人都会选择使用PHP语言,而Medoo则可以起到锦上添 ...

最新文章

  1. linux rpm找不到命令_Linux安装软件
  2. 2021信号与系统一流课程申请-说课视频规划
  3. Exchange 默认数据库删除问题
  4. 访问nfs_通过NFS访问编年引擎
  5. 24.最优布线问题(kruskal算法)
  6. Bamboo 0.2.11 发布,HAProxy 自动配置
  7. spring mvc 从Controller向页面传数据
  8. 【Win10】【亲手解决】华硕笔记本重装系统遇到的各种问题【包括重启会自动修复】
  9. c语言写股票交易软件,写股票软件
  10. INTERN: A New Learning Paradigm Towards General Vision
  11. flutter 斗音页面
  12. 如何使用 Filebeat,ILM 和数据流跨多个索引管理 Elasticsearch 数据
  13. BEVFormer论文解析
  14. 招行首发芭比娃娃MP3
  15. shell 编程中空格的使用
  16. Java版本企业招投标采购管理系统源码 一站式全流程采购招标系统
  17. 怎样使用计算机的桌面助手,360桌面助手怎么用
  18. 港大黄凯斌:6G时代的边缘智能,香农与图灵的相遇
  19. 转:PM产品设计九步法
  20. FCN训练不收敛的原因分析和最详细的FCN训练与测试自己的数据程序配置

热门文章

  1. Mapped Statements collection already contains value for xxx
  2. 【BZOJ1491】[NOI2007]社交网络 Floyd
  3. html表单站内搜,网站集成百度、Bing必应搜索引擎,在网页中实现站内全文搜索...
  4. 解决无法安装Axure RP 9(Windows 7 SP1 更新补丁)
  5. Sparten6/Kintex-7 DDR3 IP仿真实例
  6. 面对妖艳的配置文件,python小技巧来帮你!
  7. QFD质量机能展开,了解一下呀!
  8. HTML5作品展示摄影网站网页模板源码下载
  9. 肯德基真的没有什么太多吃的谨慎洋…
  10. (转)屈子:独立人格可与日月争光