目录
写作背景
内容提要
环境部署
项目配置
1.MySql 部分
2.msgpack 部分
相关代码
1.MySQL 表的设计
2.在 C++ 项目中,使用MySql C API 存取这张表
写作背景
有时候开发中会需要将一些不太基本,不太规范的数据存到数据库。比如不定长的数组,对象,这些内容无法与MySql中的普通字段类型对应上。如果将这些数组,对象中的基本数据类型拆分出来,又需要创建额外的表来存取。为了不创建额外的表 ,将复合型的数据类型和基本数据类型存在同一张表,于是有了这篇文章。
内容提要
1.通过MySql C API,以C++语言对数据库表进行操作
2.使用 msgpack 库对复杂数据,进行序列化/反序列化便于存取 BLOB 类型
环境部署
安装MySql版本:8.0
这部分内容,网络上有很多文章可供参考不再赘述。
项目配置
IDE:Visual Studio 2019,解决方案平台 x64
1.MySql 部分
项目包含目录:mysql安装目录include
项目包含库文件:mysql安装目录lib //这里我们只需要 libmysql.lib
项目执行程序需要的dll:libmysql.dll //可放到系统目录下,也可以和可执行程序同一目录
2.msgpack 部分
下载msgpack-c-cpp-4.1.1:C++ msgpack GitHub
项目包含文件:……msgpack-c-cpp-4.1.1include
相关代码
1.MySQL 表的设计
- 创建一张玩家背包表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_bag
-- ----------------------------
DROp TABLE IF EXISTS `t_bag`;
CREATE TABLE `t_bag` (
`uid` bigint(0) NOT NULL COMMENT '玩家唯一标识',
`fixed_bag` blob NULL COMMENT '玩家的固定背包,容量固定',
`var_bag` blob NULL COMMENT '玩家的无限背包,容量不固定',
PRIMARY KEY (`uid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
- 创建一张玩家背包表
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_bag -- ---------------------------- DROp TABLE IF EXISTS `t_bag`; CREATE TABLE `t_bag` ( `uid` bigint(0) NOT NULL COMMENT '玩家唯一标识', `fixed_bag` blob NULL COMMENT '玩家的固定背包,容量固定', `var_bag` blob NULL COMMENT '玩家的无限背包,容量不固定', PRIMARY KEY (`uid`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
2.在 C++ 项目中,使用MySql C API 存取这张表
-
首先是 mysql_tool.h 头文件,对 MySQL C API进行了一些封装处理便于使用
首先是 mysql_tool.h 头文件,对 MySQL C API进行了一些封装处理便于使用
#ifndef _MSYQL_TOOL_H #define _MSYQL_TOOL_H #include "mysql.h" //包含这个文件以使用 C API #include#include #include using namespace std; //数据库配置,需要修改成自己的 constexpr auto dbip = "127.0.0.1"; //数据库ip ; constexpr auto dbuser = "root"; //数据库用户 constexpr auto dbpwd = "123456"; //数据库密码 constexpr auto dbname = "test"; //数据库名字 //mysql 执行返回 //插入,查询,存储过程…… struct sReuslt { int rtCode; //错误码 , 0:成功…… MYSQL_RES* res; //结果集 void afterExecute(std::function func) { func(res); } }; //将 %s 转为 "%s" std::string getNewQuery(std::string qry) { std::string new_qry(qry); auto offset = 0; auto pos = new_qry.find("%s",offset); while (pos != std::string::npos) { new_qry = new_qry.insert(pos + 2, """); new_qry = new_qry.insert(pos, """); offset = pos + 2; pos = new_qry.find("%s", offset); } return new_qry; } //对MySql C API 进行一些封装,便于使用 class mysql_tool { private: MYSQL osql; bool is_init = false; public: void init() { mysql_init(&osql); is_init = true; } auto get() { if (false == is_init) init(); return &osql; } void connectMySql() { if (mysql_real_connect(get(), dbip, dbuser, dbpwd, dbname, 3306, NULL, 0)) cout << "数据库连接成功!n"; else { auto errcode = mysql_errno(get()); cout <<"error code : "<
- 然后就是使用部分了,这里我是用了 main.cpp 源文件
#include#include #include "mysql.h" #include #include #include #include "mysql_tool.h" #define MSGPACK_NO_BOOST //解决 无法打开包括文件: “boost/predef/other/endian.h”: No such file or directory #include "msgpack.hpp" using namespace std; //用来存储的复合对象 struct item { int id; //道具id int count; //道具数量 MSGPACK_DEFINE(id, count); //启用 msgpack 序列化,反序列化 }; void loadData(item* fixedBag, std::vector - & varBag) { fixedBag[0].id = 5; //为了简便 fixedBag[0].count = 3; fixedBag[1].id = 4; fixedBag[1].count = 20; for (size_t i = 0; i < 10; ++i) { item tmp; tmp.id = i + 2; tmp.count = 22; varBag.push_back(tmp); //10 个道具 } } int main() { mysql_tool sql; sql.connectMySql(); //连接数据库 auto ret = sql.getDBbyName("test"); //选择数据库 if (0 != ret) { sql.printError(); return -1; } item fixedBag[2] = { 0 }; //固定背包的结构 2 个道具 std::vector
- varBag; //可变背包 loadData(fixedBag, varBag); //填充数据 std::stringstream ss; msgpack::pack(ss, fixedBag); //序列化 std::string ser_str = ss.str(); std::stringstream var_bag_ss; msgpack::pack(var_bag_ss, varBag); //序列化操作 string ser_str_var_bag = var_bag_ss.str(); //执行插入 auto rst = sql.execute("INSERT into t_bag (uid, fixed_bag, var_bag) VALUES(%d,%s,%s);", 100011, ser_str.c_str(), ser_str_var_bag.c_str()); //判断插入结果 if (0 != rst) { sql.printError(); } else { cout << "insert success!" << endl; } //查询查询数据库 string query_str = "select fixed_bag, var_bag from t_bag where uid = %d"; sql.executeEx(query_str, 100011).afterExecute( [=](MYSQL_RES* res) { auto row = mysql_fetch_row(res); while (row) { auto one = row[0]; auto tow = row[1]; item newFixedBag2[2] = { 0 }; vector
- new_var_bag2; auto fb_obj_hdl = msgpack::unpack(row[0], strlen(row[0])); fb_obj_hdl.get().convert(newFixedBag2); auto nvb_obj_hdl = msgpack::unpack(row[1], strlen(row[1])); nvb_obj_hdl.get().convert(new_var_bag2); //bags* fixedBag = (bags*)one; int abc = 1111; row = mysql_fetch_row(res); } }); system("pause"); return 0; }



