共享单车(八):数据库

news2024/11/19 5:33:57

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

数据库设计

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 成功=!NULL
        LOG_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的值通常为0
    if (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=utf8

INSERT 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.coloradmin.cn/o/1687361.html

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

相关文章

BeautifulSoup4通过lxml使用Xpath,以及获取(定位)元素和其文本或者属性

环境&#xff1a;win10&#xff0c;python3.8.10 首先需要安装&#xff1a;beautifulsoup4&#xff0c;lxml 使用命令&#xff1a; pip38 install beautifulsoup4 pip38 install lxml 安装完毕后查看一下&#xff1a; 写代码&#xff1a; from bs4 import BeautifulSoup …

5.24机器人基础-入门1

参考书籍&#xff1a;《机器人学导论》John.J.Craig 机器人方面的学习和线性代数、矩阵论部分的学习密切相关&#xff0c;建议先学习线性代数会更好理解此部分内容。虽然学了线代但是能忘的都忘得差不多的我要泪目了。本文主要介绍基础的运动学和动力学区别&#xff0c;正向运…

RocketMQ 架构原理

注册中心 注册中心使用得nameserver, nameserver不会进行频繁的读写&#xff0c;所以整体的性能开销小&#xff0c;稳定性也高。 注册中心没隔10s会扫描一次所有的broker&#xff0c;如果2min没有发送心跳过来&#xff0c;就人为挂了&#xff0c;断开连接。此时会更新topic与队…

IEN在Web3.0中的性能与安全优势

随着Web3.0的快速发展&#xff0c;优化网络基础设施变得至关重要。智能生态网络&#xff08;Intelligent Ecological Network, IEN&#xff09;作为新一代网络架构&#xff0c;在提升性能与增强安全方面展现出巨大潜力。本文将深入探讨IEN在Web3.0中的技术优势&#xff0c;并展…

Linux安装Docker教程(实测可用)

前言 Docker是一个开源的应用容器引擎&#xff0c;它允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上。以下是对Docker的具体介绍&#xff1a; 技术起源&#xff1a;容器技术起源于程序员对于环境搭建与应用部署效…

data studio连接到虚拟机上的openGauss

参考&#xff1a;使用DataStudio连接本地虚拟机中的opengauss数据库_big data_白日梦想家_胖七七-华为云开发者联盟 本实验虚拟机安装的是CentOS7 数据库版本是&#xff1a;openGauss-5.0.2-CentOS-64bit-all.tar.gz 1.配置pg_hba.conf 首先使用su - omm登录到omm用户&…

FPGA搭积木之按键消抖(改进版)

目录 1.前言 2.回顾之前的设计 3.基于读者思路的设计 4.ModelSim仿真 1.前言 昨天分享的关于FPGA对机械按键消抖的设计&#xff0c;有读者指出了其中的不足&#xff0c;并给出了他的思路。今天就读者的设计思路&#xff0c;来再做一个按键消抖模块。这个程序大概是大学的时…

arping 一键检测网络设备连通性(KALI工具系列二)

目录 1、KALI LINUX简介 2、arping工具简介 3、在KALI中使用arping 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、操作示例 4.1 IP测试 4.2 ARP测试 4.3 根据存活情况返回 5、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多艺的 Linux 发…

建投数据收获客户感谢信

建投数据自2021年提出“以数据为核心的智能科技服务商”&#xff0c;并一直在为“成为国内领先的数字化转型合作伙伴”而努力&#xff0c;在赋能行业客户创造更大价值的同时&#xff0c;也陆续收到来自客户的肯定。 建投数据始终践行“成就客户&#xff0c;创新为要&#xff0…

科技引领乡村振兴新潮流:运用现代信息技术手段,提升农业生产和乡村管理效率,打造智慧化、现代化的美丽乡村

一、引言 随着科技的不断进步&#xff0c;现代信息技术已经渗透到社会的各个领域&#xff0c;成为推动社会发展的重要力量。在乡村振兴战略的背景下&#xff0c;科技的力量同样不容忽视。本文旨在探讨如何运用现代信息技术手段&#xff0c;提升农业生产和乡村管理效率&#xf…

2024 年 电工杯(B题)大学生数学建模挑战赛 | 平衡膳食食谱 | 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 CS团队倾注了大量时间和心血&#xff0c;深入挖掘解决方案。通…

k8s遇到的错误记录

时隔四年有开始重新鼓捣k8s了&#xff0c;重新安装后遇到的错误记录如下&#xff1a; Error: Package: kubelet-1.14.0-0.x86_64 (kubernetes) Requires: kubernetes-cni 0.7.5 Available: kubernetes-cni-0.3.0.1-0.07a8a2.x86_64 (kubernetes) …

自学有点吃力,需不需要报六西格玛培训班学习?

在追求职业精进和企业管理优化的道路上&#xff0c;六西格玛管理方法论已经成为不少企业和个人的首选。然而&#xff0c;自学六西格玛往往伴随着一系列挑战&#xff0c;让不少学习者感到吃力。面对这样的困境&#xff0c;我们不禁要问&#xff1a;自学有点吃力&#xff0c;到底…

Docker 部署Jenkins

1、运行镜像 docker run --namejenkins \--restartalways \--privilegedtrue \-u root \-p 8080:8080 \-p 50000:50000 \-v /home/docker/jenkins/jenkins_home:/var/jenkins_home \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-e TZ…

二十一、openlayers官网示例Custom Controls解析——自定义控件扩展Control类

官网demo地址&#xff1a; Custom Controls 这个示例讲的是如何自定义控件 首先创建了一个新的类继承了原本的Control&#xff0c;新增了一个button元素&#xff0c;然后调用了super方法将参数传给了父类。 const button document.createElement("button");button.…

《Rust奇幻之旅:从Java和C++开启》第1章Hello world 2/5

讲动人的故事,写懂人的代码 很多程序员都在自学Rust。 🤕但Rust的学习曲线是真的陡,让人有点儿怵头。 程序员工作压力大,能用来自学新东西的时间简直就是凤毛麟角。 📕目前,在豆瓣上有7本Rust入门同类书。它们虽有高分评价,但仍存在不足。 首先,就是它们介绍的Rust新…

[猫头虎分享21天微信小程序基础入门教程] 第11天:小程序的动态数据展示与实时更新

[猫头虎分享21天微信小程序基础入门教程] 第11天&#xff1a;小程序的动态数据展示与实时更新 — 第11天&#xff1a;小程序的动态数据展示与实时更新 &#x1f4ca; 自我介绍 大家好&#xff0c;我是猫头虎&#xff0c;一名全栈软件工程师。今天我们继续微信小程序的学习&a…

sCrypt受邀参加#Unlock Bitcoin活动

由Antalpha HackerHouse主办的#Unlock Bitcoin活动将于2024年6月16日至18日在美国拉斯维加斯举办&#xff0c;sCrypt创始人兼CEO刘晓晖将作为演讲嘉宾出席本次活动。 刘晓晖本次演讲的主题是&#xff1a; 《Bitcoin Smart Contracts》 请登录以下网址报名参会&#xff1a; ht…

安全牛专访美创CTO周杰:数据安全进入体系化建设阶段,数据安全管理平台应用正当时

在数字经济时代&#xff0c;数据作为生产要素发挥越来越重要的作用&#xff0c;数据安全也得到了前所未有的重视。而随着数据安全能力已经进入了相对体系化建设的阶段&#xff0c;更加智能化、协同化的新一代数据安全管理平台得到了各类企业组织的广泛关注。 本期牛人访谈邀请到…

新火种AI|复旦团队在“冷冻人脑”领域获得重大进展!人工智能是否会对此形成助力?

​在低温医学领域&#xff0c;“冷冻人脑”技术的研究和突破既是重点&#xff0c;也是难点。因为这项技术关乎着人类是否可以取得一个令人瞩目的突破——人类的生命是否能够得到延续。 早几年&#xff0c;诸如“利用人体冷冻技术将身患绝症的病人保存十几年&#xff0c;几十年…