私人博客定制----封装数据库接口

封装MySQLAPI

我们先把初始化句柄和断开句柄进行一个封装

  static MYSQL* MySQLInit(){    //1.初始化一个Mysql句柄建立连接    MYSQL* connect_fd = mysql_init(NULL);    //2.和数据库建立连接    if (mysql_real_connect(connect_fd, "127.0.0.1", "root", "123456",    "blog_system", 3306, NULL, 0) == NULL) {    printf("连接失败! %s\n", mysql_error(connect_fd));    return NULL;    }    //3.设置字符编码集    mysql_set_character_set(connect_fd, "utf8");    return connect_fd;    }        static void MySQLRelease(MYSQL* mysql) {    //释放句柄并断开连接                                                                                                                                                                                       mysql_close(mysql);     }

博客表操作的实现

接下来的实现操作,我们需要借助一个库,这个库是Json库,
大概了解一下Json
上面哪个链接可以大概了解Json,json 出自 JavaScript, 是一种非常方便的键值对数据组织格式, 目前被业界广泛使用.
C++ 中可以使用 jsoncpp 这个库来解析和构造 json 数据。但是我们并不用里面提到的CJson的库,我们是用Linux下yum源中的Json库,可以通过下面这个命令进行下载

yum install jsoncpp-devel

以下的操作相关参数都同一使用Json的方式
Json::Value jsoncpp中最核心的类,Json::Value 就表示一个具体的对象,例如我们之前设计的API

{title:"博客标题",content:"博客正文",create_time:"创建时间",tag_id:"标签id"
}

为什么我们要使用Json这个库呢?
其实最大的好处就是方便我们以后进行功能上的扩展
Json可以跨语言编程

实现插入博客

我们需要把博客对象传进去,因为一些特赦字符的原因,我们先进行转义,然后进行申请空间,这里使用智能指针来帮助我们管理内存,我们就不必在考虑其中的释放问题。最后拼装sql语句并进行返回值校验
智能指针原理

bool Insert(const Json::Value& blog) {    // 由于博客内容中可能包含一些特殊字符(\n, '', "" 等), 会导致拼装出的 sql 语句有问题.    // 应该使用 mysql_real_escape_string 对 content 字段来进行转义    // 转义只是为了让 SQL 语句拼接正确. 实际上插入成功后数据库的内容已经自动转义回来了.    const std::string& content = blog["content"].asString();    // 文档上要求转义的缓冲区长度必须是之前的 2 倍 + 1    // 使用 unique_ptr 管理内存    std::unique_ptr<char> content_escape(new char[content.size() * 2 + 1]);    mysql_real_escape_string(mysql_, content_escape.get(), content.c_str(), content.size());    // 插入的博客内容可能较长, 需要搞个大点的缓冲区(根据用户请求的长度自适应),    std::unique_ptr<char> sql(new char[content.size() * 2 + 4096]);    sprintf(sql.get(), "insert into blog_table values(null, '%s', '%s', %d,'%s')",    blog["title"].asCString(), content_escape.get(),    blog["tag_id"].asInt(), blog["create_time"].asCString());    int ret = mysql_query(mysql_, sql.get());    if (ret != 0) {    printf("执行 sql 失败! sql=%s, %s\n", sql.get(), mysql_error(mysql_));    return false;    }    return true; }    

实现查询所有博客

因为是获取所有博客内容,我们需要一个返回的结果,blogs作为输出型参数,除此之外我们还可以按照标签来筛选,初始给标签id默认为空,如果用户提供标签则进行筛选,没有提供则不进行筛选,然后执行sql语句,并判断是否成功,然后我们还需要对结果集合进行遍历打印

   bool SelectAll(Json::Value* blogs, const std::string& tag_id = "") {    //查找不需要太长的sql,固定长度就行了    char sql[1024 * 4] = {0};    // 可以根据 tag_id 来筛选结果    if (tag_id == "") {    //此时不需要按照标签来进行筛选    sprintf(sql, "select blog_id, title, tag_id, create_time from blog_table");    }    else {    //此时我们就要按标签进行筛选了    sprintf(sql, "select blog_id, title, tag_id, create_time from blog_table where tag_id = '%s'", tag_id.c_str());    }    int ret = mysql_query(mysql_, sql);    if (ret != 0) {    printf("执行 查找 失败! %s\n", mysql_error(mysql_));    return false;    }    MYSQL_RES* result = mysql_store_result(mysql_);    if (result == NULL) {    printf("获取结果失败! %s\n", mysql_error(mysql_));    return false;    }    int rows = mysql_num_rows(result);    //把结果集合写到blogs参数中,返回给调用者    for (int i = 0; i < rows; ++i) {    MYSQL_ROW row = mysql_fetch_row(result);    Json::Value blog;    //row[]中的下标和上面的select语句中写的列顺序是相关的    blog["blog_id"] = atoi(row[0]);    blog["title"] = row[1];    blog["tag_id"] = atoi(row[2]);    blog["create_time"] = row[3];     // 遍历结果依次加入到 dishes 中                                                                                                                                                                      blogs->append(blog);    }    printf("执行查找成功\n");    //mysql查询的结果集合需要记得释放    mysql_free_result(result);    return 0;}

实现查询单个博客

我们在查看单个博客时,blog同样是输出型参数,根据当前的blog_id在数据库中找到具体的内容,博客内容通过blog参数返回给调用者。这回我们只需要拼接一条sql语句即可,然后再去遍历结果集合就可以。

bool SelectOne(int32_t blog_id, Json::Value* blog) {char sql[1024 * 4] = {0};sprintf(sql, "select * from blog_table where blog_id = %d", blog_id);int ret = mysql_query(mysql_, sql);if (ret != 0) {printf("执行 sql 失败! %s\n", mysql_error(mysql_));return false;}MYSQL_RES* result = mysql_store_result(mysql_);if (result == NULL) {printf("获取结果失败! %s\n", mysql_error(mysql_));return false;}int rows = mysql_num_rows(result);if (rows != 1) {printf("查找结果不为 1 条. rows = %d!\n", rows);return false;}MYSQL_ROW row = mysql_fetch_row(result);(*blog)["blog_id"] = atoi(row[0]);(*blog)["title"] = row[1];(*blog)["content"] = row[2];(*blog)["tag_id"] = atoi(row[3]);(*blog)["create_time"] = row[4];return true;}

实现更新博客

因为要更新博客,涉及到有关正文的操作,所以需要先转义,然后申请空间再由智能指针管理

bool Update(const Json::Value& blog) {                                                                                                                                                    //此处还需要转义,                                                                                                                                                                    const std::string& content = blog["content"].asString();                                                                                                                              std::unique_ptr<char> content_escape(new char[content.size() * 2 + 1]);                                                                                                               mysql_real_escape_string(mysql_, content_escape.get(), content.c_str(), content.size());                                                                                              //插入的博客内容会有点长,我们可以尽量把缓冲区变大点                                                                                                                                  std::unique_ptr<char> sql(new char[content.size() * 2 + 4096]);                                                                                                                       //拼接sql语句                                                                                                                                                                                           sprintf(sql.get(), "update blog_table set title='%s', content='%s',tag_id=%d where blog_id=%d",                                                                                       blog["title"].asCString(),                                                                                                                                                        content_escape.get(),                                                                                                                                                             blog["tag_id"].asInt(),                                                                                                                                                           blog["blog_id"].asInt());                                                                                                                                                         int ret = mysql_query(mysql_, sql.get());                                                                                                                                             if (ret != 0) {                                                                                                                                                                       printf("执行更新博客 失败! sql=%s, %s\n", sql.get(), mysql_error(mysql_));                                                                                                          return false;                                                                                                                                                                                                                                                                                                                                                                    }                                                                                                                                                                                     printf("执行博客成功\n");                                                                                                                                                               return true;                                                                                                                                                                            }                             

实现删除博客

bool Delete(int blog_id) {char sql[1024 * 4] = {0};sprintf(sql, "delete from blog_table where blog_id=%d", blog_id);int ret = mysql_query(mysql_, sql);if (ret != 0) {printf("执行删除博客失败! sql=%s, %s\n", sql, mysql_error(mysql_));return false;}printf("删除博客成功\n");return true;
}

对博客表操作进行单元测试

void TestBlogTable(){    //方便我们进行格式化结果,打印出来的结果更好看一些    Json::StyledWriter writer;    MYSQL* mysql = blog_system::MySQLInit();    blog_system::BlogTable blog_table(mysql);    bool ret = false;    Json::Value blog;    /*    blog["title"] = "第一篇博客";                                                                                                                                                                                  blog["content"] = "我要好好学习";    blog["tag_id"] = 1;    blog["create_time"] = "2019/-/-";    bool ret = blog_table.Insert(blog);    printf("Insert:%d\n",ret);    */    //测试查找    /*Json::Value blogs;    ret = blog_table.SelectAll(&blogs);     printf("select ALl %d\n",ret);    printf("%s\n",writer.write(blogs).c_str());    */    //测试查找单个博客    /*ret = blog_table.SelectOne(1,&blog);    printf("select one %d\n",ret);    printf("blog:%s\n",writer.write(blog).c_str());//序列化,方便我们看输出    */    //测试修改博客/* blog["blog_id"] = 1;blog["title"] = "第一篇项目博客";blog["content"] = "1.博客表\n 博客'就是总结与学习',帮助我们记事。";ret = blog_table.Update(blog);printf("Update %d\n",ret);*///测试删除博客ret = blog_table.Delete(1);printf("Delete %d\n",ret);blog_system::MySQLRelease(mysql);
}

实现标签表的操作

实现新增标签

这块我们还是跟博客表的操作是一样的,都是拼装sql语句,然后执行,判断是否执行成功,打印提示。

bool Insert(const Json::Value& tag) {                                             char sql[1024 * 4] = {0};              // 此处 dish_ids 需要先转成字符串(本来是一个对象,    // 形如 [1, 2, 3]. 如果不转, 是无法 asCString)    sprintf(sql,"insert into tag_table values(null, '%s')",tag["tag_name"].asCString());    int ret = mysql_query(mysql_, sql);     if (ret != 0) {                         printf("插入标签失败! sql=%s, %s\n", sql, mysql_error(mysql_));    return false;                         }                                      printf("插入标签成功\n");               return true;                            
}         

实现删除标签

bool Delete(int32_t  tag_id) {              char sql[1024 * 4] = {0};    sprintf(sql, "delete from tag_table where tag_id = %d", tag_id);    int ret = mysql_query(mysql_, sql);    if (ret != 0) {    printf("插入标签失败! sql=%s, %s\n", sql, mysql_error(mysql_));    return false;    }    printf("插入标签成功\n");    return 0;  }

实现查看所有标签

bool SelectAll( Json::Value* tags) {    char sql[1024 * 4] = {0};    sprintf(sql, "select * from tag_table");    int ret = mysql_query(mysql_, sql);    if (ret != 0) {    printf("查找失败! %s\n", mysql_error(mysql_));    return false;    }    MYSQL_RES* result = mysql_store_result(mysql_);    if (result == NULL) {    printf("获取结果失败! %s\n", mysql_error(mysql_));    return false;    }    int rows = mysql_num_rows(result);    for (int i = 0; i < rows; ++i) {    MYSQL_ROW row = mysql_fetch_row(result);    Json::Value tag;    tag["tag_id"] = atoi(row[0]);    tag["tag_name"] = row[1];    tags->append(tag);    }    printf("查找标签成功!共找到 %d 个\n",rows);    return true;    
}    

对标签操作进行单元测试

void TestTagTable(){    MYSQL* mysql = blog_system::MySQLInit();    blog_system::TagTable tag_table(mysql);    Json::Value tags;    Json::StyledWriter writer;    /*tag["tag_name"] = "项目";    bool ret = tag_table.Insert(tag);    printf("insert %d\n",ret);    */    //测试查找    /* bool ret = tag_table.SelectAll(&tags);    printf("select all %d\n",ret);    printf("tags:%s\n",writer.write(tags).c_str());    */    //测试删除    bool ret = tag_table.Delete(1);    printf("Delete %d\n",ret);    blog_system::MySQLRelease(mysql);    
}     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

私人博客定制---服务器接口封装

实现服务器接口 我们用一个http服务器作为底层&#xff0c;但是c中并没有先成的http服务器&#xff0c;所以我在GitHub上找到一个牛人写的http服务器&#xff0c;拿来直接用&#xff0c;节省本项目开发的时间 这是服务器的链接地址 上面有详细的使用方法&#xff0c;本文就不再…

私人博客定制

项目背景 可行性方面 需求分析&#xff1a; 详细设计&#xff1a; 数据库设计 博客管理API的设计 标签相关API 服务器端的实现 对数据库操作进行封装 对服务器操作进行封装 客户端实现 具体操作 使用markdown 具体实现 测试 项目效果展示 维护 完整代码 项目…

初识c++中的函数模板

函数模板 函数模板概念 函数模板:编译器生成代码的一个规则。函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定类型版本。 函数模板格式 //要让这个函数与类型无关 //Add函数模板 template…

深入理解c++中的函数模板

非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可将该参数当成常量来使…

c++中的IO流

c语言中的IO操作 标准类型的输入输出: 输入------>数据来源是通过键盘进行输入输出------>程序中的数据输出到控制台 c语言中: scanf:输入 printf:输出 两个函数的相同点 1 —格式串 2 —不定参数 两个函数的缺陷 1 —用户要提供数据的格式—用户要记忆大量的格式串—…

201301 JAVA2~3级---走格子

请编写一个函数&#xff08;允许增加子函数&#xff09;&#xff0c;计算n x m的棋盘格子&#xff08;n为横向的格子数&#xff0c;m为竖向的格子数&#xff09;沿着各自边缘线从左上角走到右下角&#xff0c;总共有多少种走法&#xff0c;要求不能走回头路&#xff0c;即&…

复习Linux基本操作----常见指令

Linux基本操作 ls命令 ls(list):相当于windows上的文件资源管理器 语法&#xff1a; ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目…

复习Linux基础操作---权限操作

shell命令以及运行原理 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来与kernel沟…

【剑指offer】_01 (二维数组中的查找)

题目描述 在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该…

【剑指offer】_02替换空格

题目描述 请实现一个函数&#xff0c;将一个字符串中的每个空格替换成“%20”。例如&#xff0c;当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 解题思路 首先我们先算出整个字符串的长度&#xff0c;还有总共多少个空格。因为空格只占一个字节&#…

【剑指offer】_04 重建二叉树

题目描述 输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}&#xff0c;则重建二叉树并返回。 解题思路 用前序的顺序…

再谈c++中的多态

何为多态 多态的概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体点就是去完成某个行为&#xff0c;当不同的对象去完成时会产生出不同的状态。 多态的实现 在继承的体系下 基类中必须有虚函数(被virtual关键字修饰的成员函数)&#xff0c;在派生类中必须…

再谈c++中的继承

继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&#xff0c;体现了…

红黑树概念及其相关操作的实现

红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但它并不像AVL树一样&#xff0c;每个结点绑定一个平衡因子。但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过 对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c…

模拟实现STL中map和set容器

红黑树的迭代器 //红黑树的迭代器 template<class T> struct RBTreeIterator {typedef RBTreeNode<T>Node;typedef RBTreeIterator<T> Self; public:RBTreeIterator(Node* pNode nullptr):_pNode(pNode){}//具有指针操作T& operator*(){return _pNode-…

【剑指offer】_05 连续子数组最大和

题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢&#…

排序上---(排序概念,常见排序算法,直接插入,希尔排序,直接选择排序,堆排序)

排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c;若经过排序&…

排序下---(冒泡排序,快速排序,快速排序优化,快速排序非递归,归并排序,计数排序)

排序上 排序上 交换类排序 基本思想&#xff1a;所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 冒泡…

哈希的概念及其操作

哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在查找一个元素时&#xff0c;必须要经过关键码的多次比较。顺序查找时间复杂度为O(N)&#xff0c;平衡树中为树的高度&#xff0c;即O( Log2N)&#xff0c;搜索的效率取决…

软件工程---1.概述

软件的特征 抽象&#xff1a; 不可触摸&#xff0c;逻辑实体&#xff0c;可记录&#xff0c;但看不到复制成本低&#xff1a;不受物质材料的限制&#xff0c;不受物理定律或加工过程的制约&#xff0c;与开发成本相比&#xff0c;复制成本很低无折旧、受硬件制约、未完全摆脱手…