Qdbc 使用手册
** 此操作数据库框架为类mybatis,如果之前使用过此类框架,则会比较熟悉一些,所有的sql操作都采用宏函数的进行操作,方便简单。
此框架目前为测试版本,非稳定版本。版本查看:在Qdbc.h中的Qversion宏,你可以打印此宏,如果看到版本中有c,为测试版本。为s,则为稳定版本
此框架命名为Qdbc,如果有重名,则立刻修改。**
Qdbc源码地址: https://gitee.com/QdbcShen/QtOrm
dll下载地址:https://github.com/linuxguangbo/QtOrm/releases
Contents
1,快速开始
-
将Qdbc.dll拷贝到新创建的工程目录中
-
建立一个含qt的工程并且包含于SQL模块
-
添加"Qdbc.h"头文件导入其中即可快速开始
-
导入laneip表(网络检测表),数据库一定要utf-8格式,测试的数据表如下
id int(11) NOT NULL AUTO_INCREMENT , ip varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , port varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , url varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , entryno varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , etype int(255) NULL DEFAULT NULL , Status int(255) NULL DEFAULT 1 , description varchar(600) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , updatetime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP , PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=7 ROW_FORMAT=COMPACT;
表结构解释:
字段名 描述 id 默认自增长 ip 网站的ip port 网站的端口 url 网站的url entryno 网站的地点编号(‘0’:北京,‘1’:上海,‘2’:深圳,‘3’:江苏) etype 网站种类(0:‘ 企业网站 ’,1:‘ 行业网站 ’,2:‘ B2B电子商务网站 ’) description 网络状态描述 (‘网络异常,连接超时’,‘网络正常’) updatetime 更新事件,如果不填,则为当前时间 - 插入一些数据,能查询到对应的ip
#include <QtCore/QCoreApplication>
#include "dbc.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString ip;
Qselect("SELECT ip from laneip WHERE id = 2") > ip;
return a.exec();
}
2,占位符与宏格式
目前占位符分两种#{}和${}。#{}和${}与orm的类的属性要完全匹配,如何不匹配,会出现异常。#{}表示一个预处理占位符号,${} 表示简单的拼接sql
- 标签查找规则:优先找#{}在找 ,对于 {},对于 ,对于{}注意字符串类型需要加单引号
void updatetest()
{
QString sql = "UPDATE laneip SET updatetime='${updatetime}' WHERE id=${id}";
int count;
Qupdate(sql) < QDateTime::currentDateTime() < 2 > count ;
qDebug() << "update1:" << count;
}
- 查找出错
如果查找出错,则int类型为-1,指针类型为NULL,QString为NULL,需看此返回值是否有查询结果冲突。
-
对于Qselect,可根据需求返回,查询不到或者执行报错,指针类型为NULL,值类型为-1。
-
对于Qupdate,Qinsert,Qdelete,只返回int类型,执行成功,返回影响的行数。执行报错,返回-1 。
-
宏格式
所有宏格式都在Qdbc中进行查看,采取语义化的标签,尽量方便使用。此为查询语句格式:
-
Qselect 表示查询宏:对于查询 Qselect(“select * from xxx”) < arg1 < arg2 > result; 可以有多个输入,但只能一个输出。<表示输入,相当于函数参数,>表示输出,相当于函数返回值。<不可以指定为list类型,但返回值可以,一般用于查询多条语句。
-
其他语句格式:
Qdelete 表示删除宏 Qinsert 插入宏 Qdelete删除宏,此上三种宏只能有一个输出或不输出。此输出类型一定为int类型。
-
-
Qtransactional事务宏
默认放在函数的第一行,这样才能照顾到所有的sql操作,一旦某个sql操作出现了错误,则会回滚操作,否则提交,列子如下:
void transactionaltest()
{
Qtransactional();
Laneip lane;
lane.ip = "192.168.1.103";
lane.id = 2;
QString sql = "UPDATE laneip SET ip=#{ip} WHERE id=#{id}";
int count;
Qupdate("UPDATE laneip SET1 ip=#{ip} WHERE id=#{id}") < &lane > count;
lane.ip = "192.168.1.104";
lane.id = 2;
Qupdate(sql) < &lane > count;
qDebug() << "update:" << count;
}
- Qif 宏为逻辑判断,相当于if-else
- Qif(condition,va)
condition 为逻辑判断条件,支持&&,||,!
va 为此condition条件成立时候,执行va。但va一定为字符串输出- Qelif(condition,va)
condition 为逻辑判断条件,支持&&,||,!
va 为此condition条件成立时候,执行va。但va一定为字符串输出,另外一定先执行Qif
-Qelse(va)
va 为所有的condition条件不成立时候,执行va。但va一定为字符串输出,另外一定先执行Qif或Qelif
- Qelif(condition,va)
- Qswitch 宏为选择判断,相当于switch-case,此宏需要跟Qcase连用
-
Qswitch(const1)
const1 为常量,此常量支持字符串或者整形。 -
Qcase(const1,value1)
const1 为常量,此常量支持字符串或者整形。value1为匹配到的const1值
-
- Qdefault(value1)
const1 为常量,此常量支持字符串或者整形。value1为匹配不到的const1值
-
Qforeach(begin,separator,end,collection)
Qforeach 宏为循环语句,相当于for语句,此宏需单独使用
-
begin 参数为字符串,此为collection的开始点
-
separator 参数为字符串,此为collection以什么分割
-
end 参数为字符串,此为collection的结束点
-
collection 此为QString,QList,QStringList类型,QList可以用宏IntList代替
-
-
Qclear
Qclear为释放动态申请内存的指针变量,可以手动进行释放,如果不手动释放,申请的内存也会自动释放
-
QconfigPath(path,name)
此宏需要在执行sql语句之前进行配置,否则配置无效。
- path:可以指定相对路径,也可以指定觉得路径,此路径可以是相对路径也可以是绝对路径。对于路径,请用反斜杠进行路径编码。如C:/11/22 。如何填空字符串,则于可执行文件路径相同。
- name: 指定的配置文件名,如果name为空字符串,则写指定为默认的配置文件名:qjbctemplate.ini。否则以指定的配置文件名来指定。
-
QBye()
此宏用于对于在多线程情况下,线程需要不断的销毁于创建,需要在线程结束的时候放置 QBye()
-
QDBC_Id
此宏用于在多线程下定位哪个线程打印的数据,每次增加一个线程,QDBC_Id就会增加1, 如:qDebug() << QDBC_Id << Object_utils::toString(lane);
此方法为测试Qif功能
void iftest()
{
Laneip* lane = NULL;
QString ip = "192.168.1.104";
QString sql = "SELECT * FROM laneip WHERE id = "
Qif(ip == "192.168.1.104", "2")
Qelse("0");
Qselect(sql) > lane;
if (lane == NULL) {
qDebug() << "error";
return;
}
qDebug() << Object_utils::toString(lane);
}
**此方法为测试Qswitch功能,此返回的是**
void switchtest()
{
Laneip* lane = NULL;
QString ip = "192.168.1.104";
QString sql = "SELECT * FROM laneip WHERE id = "
Qswitch(ip)
Qcase("192.168.1.100","1")
Qcase("192.168.1.104","2");
Qselect(sql) > lane;
if (lane == NULL) {
qDebug() << "error";
return;
}
qDebug() << Object_utils::toString(lane);
}
此方法为测试Qforeach功能,此返回是list类型
void foreachtest()
{
qDebug() << "QHello::selectAl start";
QList<Laneip*> lanelist;
IntList ls;
ls << 2 << 3;
QString sql = "SELECT * FROM laneip where id in" Qforeach("(",",",")",ls);
Qselect(sql) > lanelist;
qDebug() << QDBC_Id << Object_utils::toString(lanelist);
}
-
Qresults 宏使用
-
此宏需要配合@result_Id,@result,@one,@many
-
#define result_Id(column,…) 此为定义id的属性,column定义为数据库列名,如果填充属性,则为自定义属性,否则为数据库列名跟属性名字相同
-
#define result(column,…) 此为定义类的属性,column定义为数据库列名,如果填充属性,则为自定义属性,否则为数据库列名跟属性名字相同
-
#define one(classname,…) 此为定义关联的类,classname为类名,可以跟属性形成多级嵌套,关联为对象或链表(只为Qlist)时使用此宏
class Laneipch : public QObject { Q_OBJECT public: Q_ATTR(int, id) Q_ATTR(QString, url) }; class Laneip :public QObject { Q_OBJECT public: Q_ATTR(int, id) Q_ATTR(QString, ip) Q_ATTR(int, port) Q_ATTR(QString, url) Q_ATTR(QString, entryno) Q_ATTR(int, etype) Q_ATTR(int, Status) Q_ATTR(QString, description) Q_ATTR(QDateTime, updatetime) Q_ASSOCIATION_OBJECT(Laneipch) }; class Place : public QObject { Q_OBJECT public: Q_ATTR(int, id) Q_ATTR(QString, name) Q_ATTR(QString, area) Q_ASSOCIATION_OBJECT(Laneipch) };
void unionselect() { QList<Place*> pl ; QString str = "SELECT pl.id as pid,pl.`name`, pl.area,l.id,l.ip,l.url,l.entryno,ch.id as chid,ch.url as urls \ from laneip L, place pl, laneipchild ch WHERE l.etype = pl.id and pl.id = ch.id ORDER BY pid asc"; Qselect(str) < Qresults( @result_Id(pid, id), @result(name), @result(area), @one(Laneip, { @result_Id(id), @result(ip), @result(url), @result(entryno), }), @one(Laneipch, { @result_Id(chid,id), @result(urls,url), }) ) > pl; Qclear(); }
-
3,orm 类定义
- 假设定义的类型为Laneip,想将类映射到数据库,那就要将类定义成如下格式:
- 从20.10版本以后需要加上头文件 #include “QdbcConfig.h”
class Laneip :public QObject
{
Q_OBJECT
public:
Q_ATTR(int,id)
Q_ATTR(QString, ip)
Q_ATTR(int, port)
Q_ATTR(QString,url)
Q_ATTR(int,entryno)
Q_ATTR(int,etype)
Q_ATTR(int, Status)
Q_ATTR(QString, description)
Q_ATTR(QDateTime,updatetime)
};
对于orm定义的类,使用Q_ATTR来包裹定义的成员变量。此宏默认会在其成员中加入get或set方法,并且大小写敏感,禁止使用static变量,并且不要试图用laneip(QObject *parent): QObject(parent)来定义。
- 属性说明
- Q_ATTR(T,member) 用此宏属性为member,类型为T。定义的属性与数据库表字段一一对应,大小写敏感。
- 此定义的类一定要继承于QObject,并且写上Q_OBJECT宏,不需要写构造函数。
- Q_ASSOCIATION_OBJECT(T2) 此宏用于关联一个对象,T2为一个对象类型,不可为指针
- Q_ASSOCIATION_LIST(T) 此宏用于关联一个链表,T2为一个链表中的对象类型,不可为指针
- ATTR_ALIAS(T,alias,member) 如果不想与数据库对应名字,则需要别名来定义。alias为别名属性, member为数据库表字段,T表示类型
别名属性:
如果不想说明数据库的字段名作为属性,则可以使用别名来定义属性。此Q_ATTR_ALIAS(Laneip,lane_url,url)
例如:Q_ATTR_ALIAS(Laneip,lane_url,url) 属性为lane_url,指定的表字段为url
属性访问:
-
读取属性:
Laneip ip;
int id = ip.id;或者int id = ip.getid(); -
写属性:
Laneip ip;
ip.id = 11;或者ip.setid(12);
属性类型规定:如果想要使用自定义类型,需要继承Object_qdbc,继承之后就可以与标签进行绑定,属性暂时只能规定: 字符串类型 QString 时间类型 QDateTime 值类型 int,bool 更多类型后续增加 。而对于自定义的变量需要定义成指针:
Laneip *lane = NULL;
QString sql = "SELECT * FROM laneip WHERE id = #{lid}";
Qselect(sql) < 3 > lane;
注意:orm采用的办自动化内存管理,会在适当的时机释放掉此内存,千万不要收到delete,如果想要delete此指针,请使用此宏函数Qclear()。此指针不会保存很长时间,如果想长期保存,需要自己定义变量来保存。
3 . 输入与输出
假设orm定义的类为T,对于输入(<) 而言,只能为T,对于输出而言,可以为T,或者 Qlist<T*> 类型,*T。
我们以Laneip的定义类来举例,详见如下表格。而对于指针类型,直接用NULL进行判断,而对于直接定义的类型,需要用 Object_utils::isNULL 进行判断。需要规定的是如果对象输出的对象为NULL,那么qdbc会默认new一个对象,否则视为已分配对象,不会重复分配。
输入(<) | 输出(>) |
---|---|
Laneip lane 或者 lane* lane = new Lane() | Laneip lane 或者 Laneip* lane = new Laneip()或者Laneip* lane=NULL或者QList<Laneip*> lane |
对于 Laneip lane = NULL而言,Qclear()会清楚此内存。但对于 Laneip lane = new Laneip()不会清理内存,请手动释放**
4,工具类: Object_utils
Object_utils 此类将有三个静态成员函数分别为:
static QString toString(T* src)
static QString toString(QList<T*>& value)
static void copy(T* src,T* dec)
static void clear(T& data)
static void clear(T* & data)
static bool isNULL(T& data)
static bool isClear(T& data)
static bool compare(T& data)
- 对于static QString toString(T* src) )静态成员函数而言,返回的是定义orm类字符串格式化的内容,以"["开头,“]”结尾,中间为类成员咱开。
此内容大致为:“[ id:3 ip:192.168.1.100 port:100 url:https://github.com/linuxguangbo/ entryno:111 etype:1 Status:1 description:正常 updatetime:2020-09-08T17:33:55 ]”
Laneip* lane = NULL;
QString sql = "SELECT * FROM laneip where id = 2";
Qselect(sql) > lane;
qDebug() << Object_utils::toString(lane);
- 对于static QString toString(T* src) )静态成员函数而言,返回的是定义orm的QList类字符串格式化的内容,以"["开头,“]”结尾,中间为类成员咱开,如果有多个类成员,则以&分割。
此内容大致为:“[ id:1 ip:127.0.0.1 port:5009 url:www.sohu.com entryno:101 etype:0 Status:2 description:网络异常,连接超时 updatetime:2020-04-30T16:54:29 && id:2 ip:192.168.1.104 port:5010 url:www.baidu.com entryno:102 etype:0 Status:1 description:网络异 常,连接超时! updatetime:2020-09-16T11:23:23 && id:3 ip:192.168.1.100 port:100 url:https://github.com/linuxguangbo/ entryno:111 etype:1 Status:1 description:正常 updatetime:2020-09-08T17:33:55 && id:5 ip:192.168.1.112 port:100 url:www.google.com entryno:111 etype:1 Status:1 description:正常 updatetime:2020-04-30T17:24:19 && id:6 ip:192.168.1.112 port:1144 url:www.google.com entryno:2 etype:2 Status:1 description:网络正常 updatetime:2020-09-08T17:24:47 && ]”
QList<Laneip*> lane;
QString sql = "SELECT * FROM laneip";
Qselect(sql) > lane;
qDebug() << Object_utils::toString(lane);
- 对于static void copy(T* src,T* dec) 成员而言,为复制定义为orm类的工具。因为继承于Qobject的类禁止拷贝复制,则可以用 copy函数来实现:
Laneip *lane = NULL;
QString sql = "SELECT * FROM laneip WHERE id = #{lid}";
Qselect(sql) < 3 > lane;
if (lane == NULL) {
qDebug() << "error";
return;
}
Laneip pp;
Object_utils<Laneip>::copy(&pp, lane);
4. 对于static void clear(T& data)静态成员函数而言,为清除引用orm类型对象。
5. 对于static void clear(T* & data)静态成员函数而言,为清除指针类型orm的对象。
6. 对于static bool isNULL(T& data) 静态成员函数而言,判断引用的orm类型是否为空,与静态成员函数isClear的返回值正好相反
7. 对于static bool isClear(T& data) 静态成员函数而言,判断引用的orm类型是否为被清除,与静态成员函数isNULL的返回值正好相反
8. 对于static bool compare(T& data) 静态成员函数而言,判断引用的orm类属性是否相同,相同返回true,不同为false
5,配置文件:qjbctemplate.ini
此为“20.09”的配置文件,如果或许增加内容,则会在配置文件中单独说明,配置文件的说明如:
[MYSQL] #暂时只要支持MYSQL
host=127.0.0.1 #数据库地址
port=3306 #数据库端口
dbname=test1 #数据库名
dbuser=root #用户名
dbpwd= #密码
isPool=true #释放开启线程,有true和false两张可选,如果是false,则[pool]不管用
timeout=2 #连接数据库的延迟
[TEMPLATE]
Loglevel=1 #日志水平,0代表全输出,1代表不输出
automemory=ture #如果为true,则有Qdbc来管理动态分配的内存,如果false则手动管理内存,Qclear宏将无效。
version=x.x.xc #版本既可以在配置文件看,也可以在Qdbc.h中查看,c为测试版本,s为稳定版
[pool]
initialPoolSize=4 #线程池的个数,暂时只支持默认的线程池,如需扩展,等待后续开发
6,版本说明
- 20.09版本:此为qdbc的第一个版本,增加了工具类Object_utils,可以通过配置文件看到版本号。
- 20.10版本:优化了程序的性能,解决了一部分内存泄漏问题,对于Readme的修订。增加了了Object_utils::compare的功能。提供了对于关联查询的支持。支持关联查询,增加了QdbcConfig的头文件,与之前的Qdbc头文件进行分离
写在最后:
希望大家提供大量的测试案列,此版暂定为测试版本,谢谢大家支持。如有bug,请在Issues中提问,或者联系邮箱1104559085@qq.com 。
如果想修修改代码,或用于其他用途,请带有Qdbc.h中的注释。另遵守Apache License 2.0协议。版本请看配置文件