共享单车(八):数据库

实现后台数据库访问模块的框架,能够实现验证请求并响应(支持数据库操作)。
在这里插入图片描述

数据库设计

class SqlTabel	//负责数据库表的创建
{
public:SqlTabel(std::shared_ptr<MysqlConnection> sqlconn) :sqlconn_(sqlconn) {}bool CreateUserInfo()        //创建用户表{const char* pUserInfoTabel = " \CREATE TABLE IF NOT EXISTS userinfo( \id            int(16)          NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT'用户id', \mobile        varchar(16)      NOT NULL DEFAULT '13000000000' COMMENT'手机号', \username      varchar(128)     NOT NULL DEFAULT '' COMMENT'用户名', \verify        int(4)           NOT NULL DEFAULT 0 COMMENT'验证',  \registertm    timestamp        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT'注册时间', \money         int(4)           NOT NULL DEFAULT 0 COMMENT'余额', \INDEX         mobile_index(mobile)   \)";if (!sqlconn_->Execute(pUserInfoTabel)){LOG_ERROR("create table userinfo table failed. error msg: %s", sqlconn_->GetErrInfo());return false;}return true;}bool CreateBikeTable()        //创建单车表{const char* pBikeInfoTabel = " \CREATE TABLE IF NOT EXISTS bikeInfo( \id            int              NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT'单车id', \devno         int              NOT NULL COMMENT'单车编号', \status        tinyint(1)       NOT NULL DEFAULT 0 COMMENT'单车状态', \trouble       int              NOT NULL DEFAULT 0 COMMENT'损坏类型编号', \tmsg          varchar(256)     NOT NULL DEFAULT '' COMMENT'损坏原因描述', \latitude      double(10, 6)    NOT NULL DEFAULT 0 COMMENT'维度', \longitude     double(10, 6)    NOT NULL DEFAULT 0 COMMENT'经度', \UNIQUE(devno)    \)";if (!sqlconn_->Execute(pBikeInfoTabel)){LOG_ERROR("create table bikeinfo table failed. error msg: %s", sqlconn_->GetErrInfo());return false;}return true;}private:std::shared_ptr<MysqlConnection> sqlconn_;
};

数据库访问

class SqlRecordSet {	//数据库访问接口
public:SqlRecordSet() :m_pRes(NULL){}explicit SqlRecordSet(MYSQL_RES* pRes)// 不能隐式构造{m_pRes = pRes;}MYSQL_RES* MysqlRes(){return m_pRes;}~SqlRecordSet() {if (m_pRes){mysql_free_result(m_pRes);	// 释放一个结果集合使用的内存}}/** 你已经设置了结果集,此时若要再次设置结果集,那么之前的结果集就访问不到了.(那之前的结果集访问不到了,之间的结果集还没来的及释放,就是内存泄漏)* 所以,你要设置结果集的前提是:结果集是空的.* 不是空的,咱们不让他设置*///设置结果集inline void SetResult(MYSQL_RES* pRes){//如果此时已经保存了结果集,那么就应该让程序报错,防止内存泄漏assert(m_pRes == NULL);if (m_pRes){LOG_WARN("the MYSQL_RES has already stored result , maybe will case memory leak\n");}m_pRes = pRes;}//获取结果集inline MYSQL_RES* GetResult(){return m_pRes;}//获取里面的行void FetchRow(MYSQL_ROW& row){row = mysql_fetch_row(m_pRes);	// 检索结果集的下一行}//返回具体行的数量inline i32 GetRowCount(){return m_pRes->row_count;}
private:MYSQL_RES* m_pRes;	// 存放mysql结果集的数据结构
};

协调处理事务

class BusinessProcessor	//负责协调处理事务
{
public:BusinessProcessor(std::shared_ptr<MysqlConnection> conn);bool init();virtual ~BusinessProcessor();private:std::shared_ptr<MysqlConnection> mysqlconn_;	//数据库连接std::shared_ptr<UserEventHandler> ueh_;        //用户事件处理器//...可以增添其它事件处理器
};

数据库操作

class MysqlConnection {
public:MysqlConnection();~MysqlConnection();MYSQL* Mysql(){return mysql_;}//初始化bool Init(const char* szHost, int nPort, const char* szUser, const char* szPasswd, const char* szDb);	//不需要/需要拿到结果bool Execute(const char* szSql);//MYSQL_RES *bool Execute(const char* szSql, SqlRecordSet& recordSet);//将pSrc特殊字符进行转义,一些特殊字符如果不转义,sql查询就会报错int EscapeString(const char* pSrc, int nSrcLen, char* pDest);void Close();//得到错误信息的方法const char* GetErrInfo();//服务断掉了,重连void Reconnect();
private:MYSQL* mysql_;//mysql的句柄,用于操作数据库
};

初始化

bool MysqlConnection::Init(const char* szHost, int nPort, const char* szUser, const char* szPasswd, const char* szDb)
{LOG_INFO("enter Init.\n");//初始化if (mysql_init(mysql_) == NULL) {   //  mysql_init 用来分配或者初始化一个MYSQL对象,用于连接mysql服务端->失败=NULL 成功=!NULLLOG_ERROR("init mysql failed %s , %d", this->GetErrInfo(), errno);return false;}//因为网络等原因,断开后自动重连char cAuto = 1;if (mysql_options(mysql_, MYSQL_OPT_RECONNECT, &cAuto)!=0)  // 用于设置 MySQL 连接的选项->成功返回0{LOG_ERROR("mysql_options MYSQL_OPT_RECONNEC failed.");}//连接//“host”的值必须是主机名或IP地址//“user”参数包含用户的MySQL登录ID//“passwd”参数包含用户的密码//“db”是数据库名称//如果“port”不是0,其值将用作TCP/IP连接的端口号//如果unix_socket不是NULL,该字符串描述了应使用的套接字或命名管道。//client_flag的值通常为0if (mysql_real_connect(mysql_, szHost, szUser, szPasswd, szDb, nPort, NULL, 0) == NULL) // 与运行在主机上的MySQL数据库引擎建立连接{LOG_ERROR("connect mysql failed : %s ", this->GetErrInfo());}return true;}

查询结果

bool MysqlConnection::Execute(const char* szSql)
{if (mysql_real_query(mysql_, szSql, strlen(szSql)) != 0)    // 执行szSql语句->成功=0 失败=-1{if (mysql_errno(mysql_) == CR_SERVER_GONE_ERROR)//断开连接就重连{Reconnect();}return false;}return true;
}bool MysqlConnection::Execute(const char* szSql, SqlRecordSet& recordSet)
{//先进行sql查询,看是否能够执行成功?if (mysql_real_query(mysql_, szSql, strlen(szSql)) != 0){if (mysql_errno(mysql_) == CR_SERVER_GONE_ERROR)    // error code{Reconnect();    // 重连 }return false;}//执行成功了,就将查到的结果设置到结果集中MYSQL_RES* pRes = mysql_store_result(mysql_);if (!pRes) {return NULL;//设置失败,返回空,说明mysql_store_result失败了}recordSet.SetResult(pRes);//将结果放入结果集return false;
}

转义

/*
* pSrc  转义前的字符
* pDest 转义后的字符
*/
int MysqlConnection::EscapeString(const char* pSrc, int nSrcLen, char* pDest)
{if (!mysql_){return 0;}// mysql必须是有效的开放式连接,将“from”中的字符串编码为转义SQL字符串,将结果置于“to”中,并添加1个终结用NULL字节return mysql_real_escape_string(mysql_, pDest, pSrc, nSrcLen);//将源src转义到目标子串dest}

相关知识

1.安装mysql c++库

sudo apt-get install libmysql++-dev
sudo systemctl mysql-server

2.安装mysql

sudo apt-get install mysql-server
sudo apt-get install mysql-client
systemctl status mysql.service #请检是否安装成功

3.进入 MySQL

sudo mysql -u root -p

4.创建数据库

CREATE TABLE `users`(`use` VARCHAR(50) NOT NULL COMMENT 'id',`pwd` VARCHAR(50) NOT NULL COMMENT 'passwd',PRIMARY KEY (`use`)
)ENGINE=INNODB DEFAULT CHARSET=utf8INSERT INTO `users`(`use`,`pwd`) VALUES ('aa' , 'bb'),('cc','dd');

5.常用操作

https://learn.microsoft.com/zh-cn/azure/mysql/single-server/connect-cpp
https://blog.csdn.net/qq_60755751/article/details/136631798

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

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

相关文章

详细分析crontab定时执行任务(附Demo | 定时清空Tomcat的实战)

目录 前言1. 基本知识2. Demo3. 实战3.1 错误版本3.2 正确版本 前言 由于用户量大&#xff0c;且导出的日志以及缓存特别多&#xff0c;急需定期删除文件 1. 基本知识 crontab 是一个用于定时执行任务的命令行工具&#xff0c;通常在 Unix 和类 Unix 系统中可用&#xff0c;表…

【微信小程序开发】小程序前后端交互--发送网络请求实战解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

三、自定义信号和槽函数(无参和有参)

需求&#xff1a; 下班后&#xff0c;小明说请小红吃好吃的&#xff0c;随便吃&#xff0c;吃啥买啥 无参&#xff1a;小红没有提出吃啥 有参&#xff1a;小红提出自己想吃的东西&#xff0c;吃啥取决于一时兴起&#xff08;emit触发&#xff09; 思路&#xff1a; 1&#xff…

Unreal Engine5 Landscape地形材质无法显示加载

UE5系列文章目录 文章目录 UE5系列文章目录前言一、解决办法 前言 在使用ue5做地形编辑的时候&#xff0c;明明刚才就保存的Landscape地形完全消失不见&#xff0c;或者是地形的材质不见了。重新打开UE5发现有时候能解决&#xff0c;但大多数时候还是没有解决&#xff0c;我下…

如何在 ASP.NET Core 中实现中间件管道

概述:借助 ASP.NET Core,中间件流水线可以作为一种轻量级、灵活的机制,使开发人员能够在请求流水线的不同阶段插入功能。这些中间件组件可以执行各种任务,例如日志记录、身份验证、授权、异常处理等。它们提供了一种封装和组织代码的方法,促进了更简洁、更易于维护的应用程…

聚观早报 | 华为畅享 70S真机图赏;vivo Y200 GT开售

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月25日消息 华为畅享 70S真机图赏 vivo Y200 GT开售 一加13部分细节曝光 马斯克谈AI未来 三星Galaxy Z Fold6将…

有一个3x4的矩阵,要求编写程序求出其中值最大的那个元素,以及其所在的行号和列号

解题思路&#xff1a; 先考虑解此问题的思路。从若干数中求最大数的方法很多&#xff0c;现在采用"打擂台"的算法。如果有若干人比武&#xff0c;先有一人站在台上&#xff0c;再上去一人与其交手&#xff0c;败者下台&#xff0c;胜者留在台上。第3个人再上…

Font shape `U/rsfs/m/n‘ in size <29.86> not available size <24.88>

解决方法&#xff1a;mathrsfs 删除这个包 其他可以参考&#xff1a;koma script - Size substitution with fontsize14 - TeX - LaTeX Stack Exchange

【C语言】深入理解指针(一)(中)

2、指针变量和解引用操作符&#xff08;*&#xff09; &#xff08;1&#xff09;指针变量 我们通过取地址操作符&#xff08;&&#xff09;拿到的地址是一个数值&#xff0c;比如&#xff1a;0x006FFD70&#xff0c;这个数值有时候是需要存储起来&#xff0c;方便后期再…

详解最新版RabbitMQ 基于RPM 方式的安装

如何选择安装版本 已经不支持的发布系列 版本最后补丁版本首次发布时间停止更新时间3.73.7.282017年11月28日2020年09月30日3.63.6.162015年12月22日2018年05月31日3.53.5.82015年03月11日2016年10月31日3.43.4.42014年10月21日2015年10月31日3.33.3.52014年04月02日2015年03…

Mybatis Cache(一)MybatisCache+Redis

前面提到了&#xff0c;使用mybatis cache&#xff0c;一般是结合redis使用。 一、demo 1、数据表 create table demo.t_address (id int auto_incrementprimary key,address_name varchar(200) null,address_code varchar(20) null,address_type int n…

计算机毕业设计Python+Scrapy+Vue.js机器学习招聘推荐系统 招聘数据可视化 招聘爬虫 招聘数据分析 大数据毕业设计 大数据毕设

桂林学院 本科生毕业论文&#xff08;设计、创作&#xff09;开题报告 二级学院 理工学院 专业 数据科学与大数据技术&#xff08;专升本&#xff09; 年级 2022级 姓名 徐彬彬 学号 202213018222 指导教师 沈岚岚 职称/学位 高级实验师 第二 导师 职称/学…

【ZYNQ】AXI-Quad-SPI SDK 开发记录 测试

前人工作 如前人工作&#xff0c;在Navigate to BSP Settings中找到历例程 file:///F:/Xilinx/Vitis/2019.2/data/embeddedsw/XilinxProcessorIPLib/drivers/spi_v4_5/doc/html/api/example.html使用XSpi_LowLevelExample例子&#xff0c;源代码的AI解析 int XSpi_LowLeve…

Java使用apache.poi生成word

加油&#xff0c;打工人&#xff01; 工作需求&#xff0c;将现有的word模板有段落和表格&#xff0c;从数据库中查出数据并填充&#xff0c;word里面也有表格数据&#xff0c;需要将excel表格数据单独处理&#xff0c;然后插入到生成好的word文档中。 下面代码模拟从数据库查出…

Kubernetes——Kubectl详解

目录 前言 一、陈述式资源管理方法 二、Kubectl命令操作 1.查 1.1kubectl version——查看版本信息 1.2kubectl api-resources——查看资源对象简写 1.3kubectl cluster-info——查看集群信息 1.4配置Kubectl补全 1.5journalctl -u kubelet -f——查看日志 1.6kubec…

物联网应用开发--STM32与机智云通信(ESP8266 Wi-Fi+手机APP+LED+蜂鸣器+SHT20温湿度传感器)

实现目标 1、熟悉机智云平台&#xff0c;会下载APP 2、熟悉新云平台创建产品&#xff0c;项目虚拟调试 3、掌握云平台生成MCU代码&#xff0c;并移植。机智云透传固件的下载 4、具体目标&#xff1a;&#xff08;1&#xff09;注册机智云平台&#xff1b;&#xff08;2&…

148.【Windows DOS命令脚本文件】

Window待处理脚本 (一)、批处理编程初步体验1.什么是批处理程序&#xff1f;(1).批处理程序的定义(2).如何编辑批处理程序 2.批处理程序可以做什么&#xff1f;(1).匹配规则删除文件(2).新建文件&#xff0c;日志等(3).创建计算机病毒等 3.一个基本的批处理文件(1).带盘符的输出…

[深入理解DDR5] 2-1 封装与引脚

3500字&#xff0c;依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解DDR》 1 DDR5 颗粒 X4 X8 X16 这里的 X8 or X16&#xff0c; 可以理解为一个DRAM芯片有几个存储阵列。“X几”。进行列寻址时会同时从几个阵列的同一个坐标位置读出数据bit来&a…

前端中 dayjs 时间的插件使用(在vue 项目中)

Day.js中文网 这是dayjs的中文文档 里面包括了使用方法 下面我来详细介绍一下这个插件的使用 Day.js 可以运行在浏览器和 Node.js 中。 一般咱直接是 npm 安装 npm install dayjs 目前应该使用的是Es6 的语法 import dayjs from dayjs 当前时间 直接调用 dayjs() 将返回…

【飞桨AI实战】基于PP-OCR和ErnieBot的智能视频问答

前言 本次分享将带领大家从 0 到 1 完成一个基于 OCR 和 LLM 的视频字幕提取和智能视频问答项目&#xff0c;通过 OCR 实现视频字幕提取&#xff0c;采用 ErnieBot 完成对视频字幕内容的理解&#xff0c;并回答相关问题&#xff0c;最后采用 Gradio 搭建应用。本项目旨在帮助初…