poco 连接mysql_[Poco]数据库操作简介
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]数据库操作简介相关推荐
- cyq.data 连接mysql_底层数据库操作类库CYQ.DATA查询
单表查询: using (MAction action = new MAction("COMP","K3")) { //查询的字段 string colstr ...
- VBA连接SQL SERVER数据库操作Excel
VBA连接SQL SERVER数据库操作Excel. Sub 按钮1_Click() Dim i As Integer, j As Integer, sht As Worksheet 'i,j为 ...
- Nginx 连接 Redis 实现数据库操作
Nginx 连接 Redis 实现数据库操作 实现的功能:当有新的连接到达Nginx时,在redis记录连接数量. 1. redis 创建数据库 安装完成redis之后,通过set connums 0 ...
- idea连接sqlserver及数据库操作
idea连接sqlserver及操作 一.在连接过程中遇到的问题: (1)数据库登录失败 (2)登录成功之后 数据库端口号怎么查看 二.代码连接数据库 ①加载驱动和连接数据库 三.数据库操作 连接详解 ...
- python连接sql sever_R和python连接SQL sever 数据库操作
在R的使用中,为了方便提取数据, 我们经常要进行数据库进行操作,接下来我们尝试使用R进行连接数据. 这里我们使用R中的RODBC进行操作, 首先,我们需要先配置ODBC资源管理器 通过任务管理器或者w ...
- jedis连接mysql_使用Jedis操作Redis数据库
Redis不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如java.C.C#.C++.php.Node.js.Go等. 在官方网站里列一些Java的客户端,有Jedis.Redisson ...
- greendao连接mysql_使用GreenDao操作数据库
大神们都说GreenDao性能最好,使用方便,最近在做一个项目,刚好用到操作本地数据库,so机缘巧合,开始学习GreenDao,顺便做一下笔记. (1)原理 我总有那么一个习惯,就是使用别人的工具,总 ...
- c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?
一.MySQL 优点: 体积小.速度快.总体拥有成本低,开源: 支持多种操作系统: 是开源数据库,提供的接口支持多种语言连接操作 : MySQL的核心程序采用完全的多线程编程.线程是轻量级的进程,它可 ...
- thinkphp5.0连接mysql_thinkphp5.0数据库操作
ThinkPHP数据库处理: 1.MySQL的数据库连接 首先配置database.php文件 使用{dump(config('database));}来查看数据库的配置项 使用 {$res = Db ...
- medoo连接mysql_Medoo PHP数据库操作类
Medoo是一个加速网站开发的最轻量的PHP数据库框架类!Medoo可以极大地加快你的PHP项目的开发.在进行Web开发的时候,很大一部分企业或个人都会选择使用PHP语言,而Medoo则可以起到锦上添 ...
最新文章
- linux rpm找不到命令_Linux安装软件
- 2021信号与系统一流课程申请-说课视频规划
- Exchange 默认数据库删除问题
- 访问nfs_通过NFS访问编年引擎
- 24.最优布线问题(kruskal算法)
- Bamboo 0.2.11 发布,HAProxy 自动配置
- spring mvc 从Controller向页面传数据
- 【Win10】【亲手解决】华硕笔记本重装系统遇到的各种问题【包括重启会自动修复】
- c语言写股票交易软件,写股票软件
- INTERN: A New Learning Paradigm Towards General Vision
- flutter 斗音页面
- 如何使用 Filebeat,ILM 和数据流跨多个索引管理 Elasticsearch 数据
- BEVFormer论文解析
- 招行首发芭比娃娃MP3
- shell 编程中空格的使用
- Java版本企业招投标采购管理系统源码 一站式全流程采购招标系统
- 怎样使用计算机的桌面助手,360桌面助手怎么用
- 港大黄凯斌:6G时代的边缘智能,香农与图灵的相遇
- 转:PM产品设计九步法
- FCN训练不收敛的原因分析和最详细的FCN训练与测试自己的数据程序配置
热门文章
- Mapped Statements collection already contains value for xxx
- 【BZOJ1491】[NOI2007]社交网络 Floyd
- html表单站内搜,网站集成百度、Bing必应搜索引擎,在网页中实现站内全文搜索...
- 解决无法安装Axure RP 9(Windows 7 SP1 更新补丁)
- Sparten6/Kintex-7 DDR3 IP仿真实例
- 面对妖艳的配置文件,python小技巧来帮你!
- QFD质量机能展开,了解一下呀!
- HTML5作品展示摄影网站网页模板源码下载
- 肯德基真的没有什么太多吃的谨慎洋…
- (转)屈子:独立人格可与日月争光