0. 前言
为什么上一篇文章鸽了很久才发出来,而且内容没啥干货?
除了最近比较忙之外,还有一个大原因:环境配置把我给卡住了……
上篇文章讲到要使用C++ Connector
,需要有MSVC
编译器支持,而且MySQL
版本越高,需要的编译器版本也越高:
我赶紧看了看我的情况:
8.0.27
版本的MySQL
需要的至少是MSVC2017
(或者MSVC2019
),而我只有VS2015
,另外又想在Qt
中使用,所以要在Qt
中安装MSVC2017
或者MSVC2019
编译器。
但又不想再装一个VS
了,于是找教程一步一步弄。
没想到,这个事情竟然这么多坑!很多的教程,真的是不明白到底是哪里没跟上……
但好在搞来搞去还是摸出来一条路子,在笔者的这篇博客中做了介绍:
Qt 添加MSVC2017编译器(2022年保姆级教程,不安装完整VS)
如果还没有配置好环境,那么建议先配置完了再往下看~
可是,配置好以后,我就声明了个变量,啥还没干就报错:
try {
Session sess("127.0.0.1", 33060, "root", "root");
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
}
CDK Error: Failed string conversion
一开始笔者以为是编译器没安装对,于是把MSVC 2015、MSVC 2017、MSVC 2019
都试一试,语句有时也改一改,换成Session
的其它构造函数,出的错五花八门:
bad allocation
string too long
CDK Error: string conversion error
CDK Error: unexpected message
······
越来越懵笔🖊,跑去官方论坛上扫楼,发现别人也会有类似的问题:
Run Time error: CDK Error: Failed string conversion
mysql-connector-cpp-8.0.20 CDK Error: Failed string conversion
似乎都没能解决我的问题的样子,于是下了个完整Visual Studio
(还是没能逃过这一劫😭😭😭),想着单步调试能救救我,确实有发现一些信息,但对于解决问题基本毫无用处……
再进到
rapidjson
里面就看不懂了……
折腾来去,还是不行,又怀疑起版本来,中途甚至跑到这里下了一个8.0.15
版本回来,使用MSVC 2015
来调试,依旧不管用……
人已经要疯了😨😨😨,但不愧是我:战术后仰–>冷静下来–>稍加思索–>下定决心之后,决定不把这玩意儿搞出来就倒立洗头,而且配置要是Qt + MSVC 2017 + MySQL 8.0.27
。
然后又看官方手册,又官方论坛扫楼,一天看到这么一条(其实这条之前看过了😭):
你是不是使用
debug
模式编译的?
将信将疑试了一下release
模式,跑了以下代码:
try {
Session sess("localhost", 33060, "root", "root");
auto list = sess.getSchemas();
for(auto l : list)
{
cout<<l.getName() << endl;
}
}
catch (const Error &err)
{
cout <<"ERROR: " <<err <<endl;
}
catch (std::exception &ex)
{
cout <<"STD EXCEPTION: " <<ex.what() <<endl;
}
catch (const char *ex)
{
cout <<"EXCEPTION: " <<ex <<endl;
}
运行结果成功打印了服务器上现有的数据库(与控制台语句show DATABASES;
一致):
不说了,人已经麻了。
发泄得差不多了,含泪进入正题😭。
本文代码主要参考官方文档:X DevAPI User Guide。
也可以下载PDF
离线看:x-devapi-userguide-en.a4.pdf;
系列文章回顾:
MySQL学习(1)-Windows环境安装和配置
MySQL学习(2)-基本概念、数据类型和简单语句
MySQL学习(3)-表格的“改”和“查”
MySQL学习(4)-批量执行SQL语句及导入记录文件
MySQL学习(5)-C++中使用MySQL(1)
1. 工程配置
1.1 基本情况
系列文章采用的MySQL
版本为8.0.27
,使用的API
为MySQL X DevAPI
,采用官方的Connector C++
提供的头文件和库文件(位于安装目录下的Connector C++ 8.0
文件夹内)。
采用的操作系统为Windows 10
,IDE
为Qt Creator 4.11.1
,编译器版本MSVC 2017 64bit
,编译类型为release
。
❗️❗️❗️切记,编译类型为Release
❗️❗️❗️
项目 | 类型 |
---|---|
操作系统 | Windows 10 |
MySQL Connector C++ 版本 | 8.0.27 |
使用API | X DevAPI |
IDE | Qt Creator 4.11.1 |
编译器 | MSVC 2017 64bit |
编译类型 | ❗️ Release |
1.2 配置
根据官方文档(5.1 Building Connector/C++ Applications: General Considerations),
要使用X DevAPI
,需要:
-
添加头文件目录和库文件,
Qt
工程需要在pro
文件中添加如下代码:#添加库查找目录,添加lib文件 LIBS += -L"C:\Program Files\MySQL\Connector C++ 8.0\lib64\vs14" -lmysqlcppconn8 #添加头文件查找目录 INCLUDEPATH += "C:\Program Files\MySQL\Connector C++ 8.0\include"
如果是
Visual Studio
开发,则需要在项目上右键–>属性,找到C/C++ -->常规–>附加包含目录,添加上方的include
目录;找到链接器–>常规–>附加库目录,添加上方的lib64/vs14
目录;找到链接器–>输入–>附加依赖项,添加mysqlcppconn8.lib
文件。也可以将文件复制到工程目录下,笔者更习惯使用安装目录下的文件这种方式。
-
将
lib64
目录下的mysqlcppconn8-2-vs14.dll
文件复制到生成exe
的目录下,此处需要复制该dll
到相对源码的路径:..\build-TestMySQL1-Desktop_Qt_5_14_2_MSVC2017_64bit-Release\release
-
包含头文件:
#include <mysqlx/xdevapi.h>
-
将编译器选择为
MSVC 2017 64bit
的release
模式:
1.3 验证
可以简单使用以下语句测试以下,看是否能在控制台打印出MySQL
服务器上所有的数据库(DATABASE
):
// main.cpp
#include "mysqlx/xdevapi.h"
#include <iostream>
using namespace mysqlx;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
try {
// 4个参数依次为:服务器地址,X Plugin端口,用户名,密码
Session sess("localhost", 33060, "root", "root");
auto list = sess.getSchemas();
for(auto l : list)
{
cout<<l.getName() << endl;
}
}
catch (const Error &err)
{
cout <<"ERROR: " <<err <<endl;
}
catch (std::exception &ex)
{
cout <<"STD EXCEPTION: " <<ex.what() <<endl;
}
catch (const char *ex)
{
cout <<"EXCEPTION: " <<ex <<endl;
}
system("pause");
return 0;
}
2. 正式学习X DevAPI
2.1 与控制台概念对应的类
将官方文档一路看过来,发现不一定要跟着它一步步来,可以直接看各种类的功能。下图是官方文档中的类图:
由于我们已经学过控制台对MySQL
的操作,可以将上图简单理解为下表:
控制台中的概念 | API 中的类 |
---|---|
Client | Session |
DATABASE | Schema |
TABLE | Table |
❓ | Collection |
前三个比较好理解就不再多说,对于Collection
,官方的解释是:相同类型的Document
被组合在一起,储存在数据库中即为Collection
,X DevAPI
使用Collection
对象存储、获取Document
。
看完了这个解释,笔者依旧不太清楚,暂时留着这个问题,看今后的学习中是否能更清晰一些。
另外,根据在控制台上,目前已经学习的操作中,能够操作Session
与服务器建立连接,然后拿到各种数据库Schema
,再拿到数据库中的Table
,对其中的记录进行操作就足够了。
接下来我们一起来看看这些个基本操作吧~
2.2 热身代码
都是些很简单的内容,就不多展开了,直接上代码:
// main.cpp
#include "mysqlx/xdevapi.h"
#include <iostream>
using namespace mysqlx;
using std::cout;
using std::endl;
int main()
{
try {
// 连接到服务器
Session sess("localhost", 33060, "root", "root");
// 创建一个叫 test 的数据库,如果已经存在,则获取该数据库
Schema db = sess.createSchema("test", true);
Table tbl = db.getTable("students");
if(!tbl.existsInDatabase())
{
cout<<endl<<"表格不存在,创建中……"<<endl;
sess.sql("USE test;").execute();
sess.sql("CREATE TABLE students( name VARCHAR(10), age INT, score INT);").execute();
}
tbl = db.getTable("students");
// 打印所有数据
cout<<"\n修改前:"<<endl;
RowResult res = tbl.select("*").execute();
for(auto r:res)
{
for(unsigned i = 0; i < res.getColumnCount(); ++i)
cout<<r[i] << '\t';
cout<<endl;
}
cout<<"\n修改中……"<<endl;
tbl.insert("name", "age", "score").values("Bob", "15", "90").execute();
tbl.insert("name", "age", "score").values("Peter", "15", "99").execute();
tbl.insert("name", "age", "score").values("Mary", "13", "100").execute();
cout<<"\n修改后:"<<endl;
res = tbl.select("*").execute();
for(auto r:res)
{
for(unsigned i = 0; i < res.getColumnCount(); ++i)
cout<<r[i] << '\t';
cout<<endl;
}
cout<<"\n删除表格……"<<endl;
sess.sql("USE test;").execute();
sess.sql("DROP TABLE students;").execute();
sess.dropSchema("test");
}
catch (const Error &err)
{
cout <<"ERROR: " <<err <<endl;
}
catch (std::exception &ex)
{
cout <<"STD EXCEPTION: " <<ex.what() <<endl;
}
catch (const char *ex)
{
cout <<"EXCEPTION: " <<ex <<endl;
}
}
代码的输出结果:
稍微总结一下API
的用法:
Session
类似于客户端,用来连接MySQL
服务器的,而且创建对象后,参数正确就能直接连上服务器而不需要调用其它函数;比较方便的创建对象方法是:
Session se(host, port, user, password);
Schema
类似于数据库(DATABASE),通过Session::getSchema(name)
获取数据库对象,也可以createSchema()、dropSchema()
创建、删除数据库对象;Table
是表格,通过Schema::getTable(name)
获取表格对象,X DevAPI
没有提供表格的创建和删除接口,但可以通过下一条实现;- 从上述源码来看,大部分对表格记录的操作,都需要接上
execute()
函数才会被执行;事实上,如果语句的返回类型是Executable
对象,则需要调用其execute()
函数以执行; - 可以通过
Session::sql(sqlStatement)
来执行SQL
语句,这提供了极大的灵活性,不过似乎对大家的SQL
语法基础提出了挑战;
本文就先学到这里~感觉也够大家操作一会儿的了👻
3. 总结
- 使用
X DevAPI
,需要包含Connector
的头文件,链接对应lib
文件,并将dll
文件复制到exe
目录下; - 如果是默认安装的
Connector C++
,需要采用release
模式编译; X DevAPI
的几个类:Session、Schema、Table
分别可以和控制台的客户端、DATABASE
、TABLE
对应上;- 可以通过
API
函数创建、删除数据库(createSchema(name)
和dropSchema(name)
),但没有函数直接创建、删除表格; Session::sql()
函数可以生成SQL
语句,再调用Executable::execute()
函数执行语句;
如有错误欢迎指正,共同进步~
今天你学废了吗?