01-线程池项目背景:C++的数据库操作

news/2024/7/24 2:40:29 标签: c++, 数据库

从0开始学习C++与数据库的联动

1.原始方式-使用MySQL Connector/C 提供的API查询

1.1 数据库预操作

我的本地电脑上有mysql数据库,里面预先创建了一个database名叫chat,用户名root,密码password。

1.2 Visual Studio预操作

在Windows上使用VS需要加一些路径之类的,这样才可以使用MySQL C API。否则,无法找到mysql.h,无法正常链接dll、lib,无法编译。
1.下载MySQL Connector/C;
2.配置包含目录和库目录:
“C/C++” -> “常规” -> “附加包含目录”,添加MySQL Connector/C的include目录。
“链接器” -> “常规” -> “附加库目录”,添加MySQL Connector/C的lib目录。
3.配置链接库:
在“链接器” -> “输入” -> “附加依赖项”,添加以下库文件:
libmysql.lib:MySQL C API的静态库。
mysqlclient.lib:MySQL C API的动态链接库。
4.拷贝运行时依赖项: 将MySQL Connector/C的bin目录添加到系统的PATH环境变量中,并将libmysql.dll文件复制到vcxproj文件所在的目录。

1.3 简单查询程序

1.下面是一个单线程的程序,所有的数据库连接和查询都是在主线程中执行的。(里面可能有一些不安全的操作,方便理解没有管,比如close函数里传nullptr是不安全的,NULL最好改成nullptr便于与0值区分等。)
2.mysql.h声明了MYSQL、MYSQL_ROW、MYSQL_RES等结构体和一些mysql_init这样的函数,必须包含这个头文件,编译才不会出错。
从https://dev.mysql.com/doc/c-api/8.0/en/c-api-basic-function-reference.html摘了一些出来,可跳转链接看具体的接口参数
结构体:
在这里插入图片描述
函数接口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <mysql.h> // 假设使用MySQL数据库

int main() {
    // 步骤1:建立数据库连接
    MYSQL* conn = mysql_init(NULL);
    if (conn == NULL) {
        std::cerr << "Failed to initialize MySQL connection." << std::endl;
        return -1;
    }

    if (mysql_real_connect(conn, "localhost", "root", "password", "chat", 0, NULL, 0) == NULL) {
        std::cerr << "Failed to connect to MySQL database." << std::endl;
        mysql_close(conn);
        return -1;
    }

    // 步骤2:执行SQL查询
    const char* query = "SELECT * FROM user";
    if (mysql_query(conn, query) != 0) {
        std::cerr << "Failed to execute SQL query." << std::endl;
        mysql_close(conn);
        return -1;
    }

    MYSQL_RES* result = mysql_store_result(conn);
    if (result == NULL) {
        std::cerr << "Failed to store MySQL result." << std::endl;
        mysql_close(conn);
        return -1;
    }

    // 处理查询结果
    MYSQL_ROW row;
    while ((row = mysql_fetch_row(result)) != NULL) {
        // 处理每一行的数据
        std::cout << "Column 1: " << row[0] << ", Column 2: " << row[1] << std::endl;
    }

    // 释放查询结果
    mysql_free_result(result);

    // 步骤3:断开数据库连接
    mysql_close(conn);

    return 0;
}

2.将上述API查询封装到类里,调用自己的函数查询

上面的代码主要是用到了mysql_init,mysql_real_connect,mysql_query,mysql_store_result,mysql_free_result,mysql_close这些mysql.h里声明的一些函数。如果我们想用这些函数进行对MYSQL数据库内数据的操作,用的是MYSQL*类型的指针conn进行操作。

  1. 首先,MYSQL* conn = mysql_init(NULL);也即真正malloc了一个空间,分配和初始化了一个 MYSQL 结构体实例,并返回指向该实例的指针conn。这个实例用于存储数据库连接所需的所有信息。
  2. mysql_real_connect 函数建立实际的数据库连接,并使用 MYSQL 结构体来保存连接的详细信息。
  3. 之后,无论是查询(mysql_query)、获取结果(mysql_store_result)还是关闭连接(mysql_close),都需要使用这个 MYSQL* 类型的指针。这是因为所有这些操作都是在特定的数据库连接会话上执行的,而 conn 指针正是指向这个会话的。

那么,在此基础之上,我们可以将这些函数进一步的封装,用一个类中的成员函数去分别调用它们。具体而言,我们自己定义一个Connection类,里面放一个私有成员对象MYSQL* _conn指针,以及构造、析构、连接、更新、查询函数,而这些函数又分别调用了初始的mysql_init,mysql_real_connect,mysql_query,mysql_store_result,mysql_free_result,mysql_close这些mysql.h里声明的一些函数,调用的参数是初始函数所需的参数加上conn指针。在我们自己实现的函数里,还可以额外加一些LOG语句。当我们对这个类进行实例化的时候,用类实例.成员函数()就可以真正对数据库进行增删改查。

代码分为4个文件,Connection.h、Connection.cpp、main.cpp,以及最简单的日志打印(仅仅使用了一个宏,而未用到任何日志库。)里面把之前的store换成了use,这样可以减轻内存的使用,直接按行输出而不用保存。

Connection.cpp:

// 实现对数据库的增删改查
#pragma once
#include <iostream>
#include "Connection.h"
#include "public.h"


//构造函数    mysql_init 函数用于初始化一个新的 MYSQL 结构体实例。这是建立数据库连接之前的准备步骤。
//分配并初始化一个新的 MYSQL 结构体,返回一个指向这个新结构体的指针;如果分配失败,返回 NULL。
Connection::Connection() {
	_conn = mysql_init(nullptr);
}

//真正的连接
bool Connection::connect(string ip, string user, string password, string dbname, unsigned short port) {
	MYSQL* p = mysql_real_connect(_conn,ip.c_str(), user.c_str(), password.c_str(), dbname.c_str(), port, nullptr, 0);//.c_str() :将string转换为 const char* 类型
	return p != nullptr;
}

//增删改,只要返回bool的一些操作
bool Connection::update(string sql) {
	if (mysql_query(_conn, sql.c_str())) {//当 mysql_query() 返回 0 时,表示查询语句成功执行
		LOG("更新失败:" + sql);
		return false;
	}
	return true;
}

//查并返回结果,实际上就是存
MYSQL_RES* Connection::query(string sql) {
	if (mysql_query(_conn, sql.c_str())) {
		LOG("查询失败:" + sql);
		return nullptr;
	}
	return mysql_use_result(_conn);
}

//析构函数(关闭连接)
Connection::~Connection() {
	if (_conn != nullptr)
		mysql_close(_conn);
}

Connection.h:

// 实现对数据库的增删改查
#pragma once
#include <mysql.h>
#include <string>
using namespace std;

class Connection {
public:
	Connection();
	~Connection();	//析构函数(关闭连接)
	bool connect(string ip, string user, string password, string dbname, unsigned short port);	//真正的连接
	bool update(string sql);	//增删改,只要返回bool的一些操作
	MYSQL_RES* query(string sql);	//查并返回结果,实际上就是存

private:
	MYSQL* _conn;
};

public.h:

#pragma once
#define LOG(str)\
	cout<<__FILE__<<":"<<__LINE__<<" "<<__TIMESTAMP__<<":"<<str<<endl;

main:

#include "Connection.h"

int main() {
	Connection conn;
	conn.connect("localhost", "root", "password", "chat", 3306);

	string sql = "insert into user (name, age, sex) values ('zhang san' ,18, 'male');";
	conn.update(sql);
//这里没有测试query
	return 0;
}

在这里插入图片描述
可以发现原本chat database里面user表里没有数据的,执行了该程序之后成功插入了一行数据。并且,id一开始设置成了自增字段,就没有手动指定,只插入了(name, age, sex),它会自动从1开始填。


http://www.niftyadmin.cn/n/5306349.html

相关文章

Vue3 使用 Teleport 封装 一个 Dialog

文章目录 什么是Teleport ?用法:1. 通过 to 指定传送的位置2. 禁用 teleport3. 共享一个 Teleport封装一个Dialog效果:什么是Teleport ? 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。 简单的说,Telep

Github 2024-01-05 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-05统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目3Jupyter Notebook项目2Java项目2非开发语言项目1Rust项目1QML项目1C项目1 系统设计指南 创建周期…

Certum与Geotrust的OV多域名证书

Certum和Geotrust都是知名的CA认证机构&#xff0c;旗下的SSL证书产品丰富&#xff0c;有单域名SSL证书、多域名SSL证书以及通配符SSL证书。这些SSL数字证书作为一种重要的网络安全产品&#xff0c;能够实现数据加密和身份验证&#xff0c;保障网站的安全性和隐私性。OV多域名S…

docker daemon.json配置bip项需要注意的地方

docker是现在部署服务比较常用的一种方式&#xff0c;但是docker0网络默认为172.17.x.x网段&#xff0c;172.17这个网段是私有化ip段&#xff0c;而且在企业内部使用比较常见的一个网段&#xff0c;docker0创建后会创建一个172.17网段的路由&#xff08;可以通过ip route查看&a…

快速、准确地检测和分类病毒序列分析工具 ViralCC的介绍和详细使用方法, 附带应用脚本

介绍 viralcc是一个基因组病毒分析工具&#xff0c;可以用于快速、准确地检测和分类病毒序列。 github&#xff1a;dyxstat/ViralCC: ViralCC: leveraging metagenomic proximity-ligation to retrieve complete viral genomes (github.com) Instruction of reproducing resul…

【大数据进阶第三阶段之Hive学习笔记】Hive安装

1、环境准备 安装hadoop 以及 zookeeper、mysql 【大数据进阶第二阶段之Hadoop学习笔记】Hadoop 运行环境搭建-CSDN博客 《zookeeper的安装与配置》自行百度 《Linux环境配置MySQL》自行百度 2、下载安装 CSDN下载&#xff1a;https://download.csdn.net/download/liguohuat…

【心得杂记】简单聊聊限制高速面阵相机性能的因素

研究了限制高速面阵相机发展的因素&#xff0c;感觉就是揭开了薄雾面纱之后的复杂。 个人观点&#xff0c;不保证全对~ 欢迎讨论~ 高速相机是一个整体&#xff0c;涉及的各个零部件和模组很多&#xff0c;每个环节都会影响相机指标的提高。 高速相机主要包括的核心部件有&#…

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 编译构建及此过程中的踩坑填坑(3)

接前一篇文章&#xff1a;玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 编译构建及此过程中的踩坑填坑&#xff08;2&#xff09; 上一篇文章结束时在等待提示的各依赖包下载安装后的编译结果&#xff0c;但是很遗憾&#xff0c;编译并没有最终完成&#xff0c;既未成功也没有失…