#MySQL在C++中的基本`api`讲解

    • 一、创建驱动程序实例
    • 二、连接服务器
      • 为什么使用`tcp://`
      • 不使用`tcp://`会怎样?
      • 其他协议示例
      • 连接到具体的数据库
    • 创建SQL语句
      • Statement
      • `PreparedStatement`
      • 执行时机
    • 处理结果
        • 1. 遍历结果集
        • 2. 获取列值
        • 3. 检查结果集是否为空

​ 在上篇文章中我介绍了MySQL在C语言中的基本 api,虽然只是基本的接口,但是我们依旧可以发现有这许多问题,比如,创建对象后必须手动释放,查询结果后必须手动释放否则就会有大量的内存泄漏问题出现,当然在C语言中对于MySQL多线程的把握,需要大量的锁去实现,这不仅提高代码的复杂程度,更是进一步的把后续的维护成本大大提升。

而回看C++的三大特性,封装、继承、多态,无论是其中蕴含的RAII,对于锁的更加灵1活的使用,还是衍生出来的设计模式(如:单例模式)和池化技术,以及后对于异常的处理的都简化了代码的编写。

本文将提供一个简单的demo代码,并逐步解释其中的含义,带你快速上手基本的api

首先,确保你已经安装了MySQL Connector/C++库。可以从MySQL官网下载安装。

#include <mysql_driver.h>
#include <mysql_connection.h>
#include <cppconn/statement.h>
#include <cppconn/resultset.h>
#include <cppconn/exception.h>
#include <iostream>int main() {try {// 创建驱动程序实例sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();// 通过驱动程序创建连接std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "username", "password"));// 连接到具体的数据库conn->setSchema("test_db");// 创建语句对象std::unique_ptr<sql::Statement> stmt(conn->createStatement());// 执行查询并获取结果集std::unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT id, name FROM test_table"));// 遍历结果集并输出结果while (res->next()) {std::cout << "ID: " << res->getInt("id");std::cout << ", Name: " << res->getString("name") << std::endl;}} catch (sql::SQLException& e) {std::cerr << "SQLException: " << e.what() << std::endl;std::cerr << "SQLState: " << e.getSQLState() << std::endl;}return 0;
}

一、创建驱动程序实例

创建驱动程序实例是使用MySQL Connector/C++库与MySQL数据库进行交互的第一步。这一步骤是通过调用get_mysql_driver_instance方法来实现的。其本质是用于获取MySQL_Driver类的单例实例。这个方法确保在整个程序中只存在一个驱动程序实例。

sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance();`

其中1、MySQL Connector/C++库使用了一些命名空间来组织其类和函数。sql::mysql命名空间包含了专门用于MySQL数据库的类和函数。

2、MySQL_Driver类是MySQL Connector/C++库的一个核心类,它实现了与MySQL数据库的连接管理。这个类的实例负责创建和管理与MySQL服务器的连接。

执行过程

  1. 调用get_mysql_driver_instance:
  • 当你调用sql::mysql::get_mysql_driver_instance()时,该方法会检查是否已经存在一个MySQL_Driver实例。
  • 如果不存在,它会创建一个新的实例。
  • 如果已经存在,它会返回现有的实例。
  1. 返回驱动程序实例:
  • 该方法返回一个指向MySQL_Driver实例的指针。

为什么需要驱动程序实例

驱动程序实例是与MySQL数据库通信的核心组件。通过这个实例,你可以:

  • 创建与数据库服务器的连接。
  • 执行SQL查询和命令。
  • 管理连接池和其他底层细节。

二、连接服务器

std::unique_ptr<sql::Connection> conn(driver->connect("tcp://127.0.0.1:3306", "username", "password"));
conn1->setSchema("test_db1");

这里我主要要讲一下这里的第一个参数,这个字符串由三部分组成:

  • protocol:通信协议。对于MySQL数据库,通常使用tcpsocket
  • host:数据库服务器的主机名或IP地址。
  • port:数据库服务器监听的端口号。

在这个例子中:

  • tcp:表示使用TCP/IP协议进行连接。
  • 127.0.0.1:表示连接到本地主机(localhost)。
  • 3306:MySQL数据库默认的端口号。
  • “username”:数据库的用户名。
  • “password”:数据库的密码。

为什么使用tcp://

  1. 明确通信协议:通过指定tcp://,明确告知驱动程序使用TCP/IP协议进行连接。这在需要明确区分连接方式时非常有用。例如,如果数据库服务器在本地,并且你想通过Unix域套接字(socket)连接而不是TCP/IP,可以使用socket://
  2. 灵活性和兼容性:使用标准的URL格式,可以灵活地切换不同的协议和地址,适应不同的部署环境和需求。

不使用tcp://会怎样?

如果你省略tcp://,通常默认会使用TCP/IP协议,但明确指定协议更为严谨,特别是在配置和调试数据库连接时。某些驱动程序和配置环境可能要求明确指定协议,以避免歧义或连接错误。

其他协议示例

  • socket://:用于通过Unix域套接字连接到MySQL数据库(仅适用于Unix/Linux系统)。
std::unique_ptr<sql::Connection> conn(driver->connect("socket:///path/to/socket", "username", "password"));
  • 普通连接(不指定协议):有些情况下可以省略协议前缀,依赖默认设置。
std::unique_ptr<sql::Connection> conn(driver->connect("127.0.0.1:3306", "username", "password"));

省略协议前缀通常也会使用TCP/IP协议,但明确指定协议更加严谨和可读。

连接到具体的数据库

使用创建的连接对象的 setSchema 方法选择具体的数据库。

conn1->setSchema("test_db1");

注意每个连接都是独立的,可以连接到不同的数据库实例或同一数据库实例下的不同数据库。

创建SQL语句

在C++的apisql语句分为PreparedStatement和不带参数的Statement,他们两者是有一定差别的

Statement

Statement 对象主要用于执行静态的、不带参数的 SQL 语句,例如 SELECTINSERTUPDATEDELETE。它适合用来执行那些不需要动态参数的简单 SQL 语句,其中的值是固定的,不会根据不同的输入而改变。Statement 对象的使用可以简化代码,但它不如 PreparedStatement 安全,因为不提供防止 SQL 注入的保护。

std::unique_ptr<sql::Statement> stmt(conn->createStatement());
std::unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT id, name FROM test_table"));

在上面的demo中我们发现使用 Statement 对象时,执行 SQL 查询和获取结果是一步完成的。你需要在调用 executeQueryexecuteUpdate 等方法时传入 SQL 语句,并且方法会立即执行该语句并返回结果。

PreparedStatement

PreparedStatement主要用于参数化查询重复执行相同查询执行批量操作 等场景

// 创建 PreparedStatement 对象,并绑定 SQL 语句
std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement("SELECT id, name FROM test_table WHERE id = ?"));// 第一次设置参数并执行查询
pstmt->setInt(1, 1); // 第一个参数位置,值为1
std::unique_ptr<sql::ResultSet> res1(pstmt->executeQuery());

PreparedStatement给人的感觉是像是封装了一个函数然后通过用一些set…函数经行‘传参’改变这个语句中的占位符中的字母,实现多种查询,每次查询是将占位符经行改变,而不是重新输入一个SQL语句。这样的函数有

setInt(n, 1):
设置第n个占位符(?)为整数值1。
setString(n, "Alice"):
设置第n个占位符(?)为字符串值"Alice"。
setInt(n, 25):
设置第n个占位符(?)为整数值25。
setDouble(n, 50000.50):
设置第n个占位符(?)为双精度浮点数值50000.50。
setBoolean(n, true):
设置第n个占位符(?)为布尔值true。

执行时机

  • 当调用 executeQueryexecuteUpdateexecute 方法时,SQL 语句被发送到数据库服务器并实际执行。
  • executeQuery 用于 SELECT 语句,返回一个 ResultSet 对象用于遍历查询结果。
  • executeUpdate 用于 INSERTUPDATEDELETE 等语句,返回受影响的行数。
  • execute 是一个通用方法,可以执行任何 SQL 语句,并需要根据返回结果进一步处理。

处理结果

上面我们提到在执行sql语句时会用sql::ResultSet 类型将结果封存,所以处理结果的过程,就是遍历sql::ResultSet获取值的过程。

以下是一些处理结果集的基本操作:

1. 遍历结果集

通过 next() 方法遍历结果集中的每一行:

while (res->next()) {int id = res->getInt("id");std::string name = res->getString("name");std::cout << "ID: " << id << ", Name: " << name << std::endl;
}

可以看到->next()在单个方法调用中合并了“移动到下一个元素”和“检查是否存在更多元素”这两个操作。这种设计使得遍历结果集变得简单和高效。

2. 获取列值

通过列名或列索引来获取列值:

int id = res->getInt("id"); // 使用列名
std::string name = res->getString("name");int id = res->getInt(1); // 使用列索引(从 1 开始)
std::string name = res->getString(2);
3. 检查结果集是否为空

在遍历之前可以检查结果集是否为空:

if (!res->next()) {std::cout << "No data found." << std::endl;
} else {// 重置游标到第一行res->beforeFirst();while (res->next()) {int id = res->getInt("id");std::string name = res->getString("name");std::cout << "ID: " << id << ", Name: " << name << std::endl;}
}

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

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

相关文章

告别暗黄,唤醒肌肤

&#x1f3ad; 想象一下&#xff0c;你的皮肤是舞台上的主角&#xff0c;但最近它似乎有些“疲惫”和“黯淡”&#xff0c;仿佛失去了往日的星光✨。别急&#xff0c;今天&#xff0c;我要为你揭秘一个能让肌肤重新焕发光彩的“魔法”——胶原蛋白&#xff01;&#x1f3a9; &a…

docker查看容器目录挂载

查看命令 docker inspect --format{{ json .Mounts }} <container_id_or_name> | jq 示例 docker inspect --format{{ json .Mounts }} af656ae540af | jq输出

FreeRTOS笔记 - 二(正点原子)

一&#xff0c;任务创建和删除 具体的参数&#xff08;看视频&#xff09; 1&#xff0c;动态和静态创建的区别 动态: 任务的任务控制块以及任务的栈空间所需的内存&#xff0c;均由FreeRTOS从 FreeRTOS 管理的堆中分配。 静态: 任务的任务控制块以及任务的栈空间所需的内存&am…

vscode设置编辑器文件自动保存

步骤 1.打开vscode的设置 2.在搜索栏输入关键字“保存”&#xff1b; 在 Files: Auto Save 设置项&#xff0c;选择自动保存的模式

java使用资源过高排查

在生产环境中有可能出现某java程序使用资源特别严重&#xff0c;这就需要找到该java进程&#xff0c;然后通过进程去找到是哪个线程的问题&#xff0c;这里我们就是用pidstat工具来排查一下 安装pidstat工具 yum -y install sysstat 查看java服务的pid jps 通过pid查看线…

C# WinForm —— 25 ProgressBar 介绍与使用

1. 简介 用于显示某个操作的进度 2. 常用属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 pbar 开头ContextMenuStrip右键菜单Enabled控件是否可用ForeColor用于显示进度的颜色MarqueeAnimationSpeed进度条动画更新的速度&#xff0c;以毫秒为单位M…

CSAPP Lab08——Proxy Lab完成思路

蓝色的思念 突然演变成了阳光的夏天 空气中的温暖不会很遥远 ——被风吹过的夏天 完整代码见&#xff1a;CSAPP/proxylab-handout at main SnowLegend-star/CSAPP (github.com) Q&#xff1a;计算机网络中port的作用是什么&#xff1f; A&#xff1a;在计算机网络中&#xff…

qt中实现多语言功能

qt中实现多语言功能 原理&#xff1a; 其本质就是生成ts文件&#xff0c;然后使用Linguist软件手工翻译&#xff0c;再生成qm文件&#xff0c;最后在主程序的开始加载不同的qm文件&#xff0c;实现多语言。 步骤&#xff1a; 修改程序文件 在pro文件中加入说明 TRANSLATI…

Socket网络通讯入门(一)

提示&#xff1a;能力有限&#xff0c;不足以及错误之处还请指出&#xff01; 文章目录 前言一、 计算机网络 OSI、TCP/IP、五层协议 体系结构1.OSI七层模型每层的作用2.TCP/IP协议分成3.五层协议体系结构 二、Socket服务端和客户端 简单通信1.服务端代码2.客户端 总结 前言 简…

vs - 在win10中安装vs2013update5

文章目录 vs - 在win10中安装vs2013update5概述笔记直接安装vs2013-update5报错先安装vs2013原版安装 vs2013 update5测试备注END vs - 在win10中安装vs2013update5 概述 用VS2019写的程序&#xff0c;在早期windows(e.g. win7, win8.1)上安装时&#xff0c;需要UCRT。 UCRT是…

SpringBoot整合jasypt加密配置文件敏感信息

SpringBoot整合jasypt加密配置文件敏感信息 在项目中我们需要对配置文件的一些敏感信息进行加密处理&#xff0c;比如数据库账户密码&#xff0c;避免直接暴露出来&#xff0c;这种场景常常用于生产环境&#xff0c;我们不想让开发人员知道生产库的密码&#xff0c;有运维人员…

基础篇01——SQL的基本语法和分类

MySQL数据库安装与基本使用 安装教程参见&#xff1a;通过zip安装MySQL 通过命令行启动和停止MySQL服务命令 前提&#xff1a;安装MySQL成功之后 启动服务&#xff1a;net start mysql 停止服务&#xff1a;net stop mysql 通过命令行连接mysql 可以通过mysql的客户端命令行…

入手戴尔R720,通过iDRAC查看系统信息

想入手服务器很久了&#xff0c;一直担心功耗太高&#xff0c;今天狠心搞了一台戴尔服务器R720。 需求 开虚拟机&#xff0c;核心数要多 学习以下 Windows云桌面AD域控office online serverubuntu试验机 随便折腾不怕玩坏 最好两个网口以上 稳定 四个以上硬盘位 ‍ 为什么是…

在AutoDL上部署百川2大模型

在AutoDL上部署百川2大模型 AUTO DL相关 官网地址 选择容器实例 租用新实例 选择配置 我这里选择3090 , 硬盘尽量选择可以扩容的 , CUDA版本尽量高一点 选择镜像 先将机器关机 先扩容一下数据盘 50G就可以了 然后选择无卡模式开机 因为无卡模式下开机费用会变低 使用JupyterL…

1.3Java对象和类

Java作为一种面向对象语言。支持以下基本概念&#xff1a; 多态继承封装抽象类对象实例方法重载 本节我们重点研究对象和类的概念。 对象&#xff1a;对象是类的一个实例&#xff08;对象不是找个女朋友&#xff09;&#xff0c;有状态和行为。例如&#xff0c;一条狗是一个…

BrainGPT1,一个帮你b站点歌放视频的多模态多轮对话模型

BrainGPT1&#xff0c;一个帮你b站点歌放视频的多模态多轮对话模型 返回论文目录 项目地址 模型地址 作者&#xff1a;华东师范大学&#xff0c;计算机科学与技术学院&#xff0c;智能教育研究院的小怪兽会微笑。 介绍 BrainGPT1是一个工具调用多轮对话模型&#xff0c;与G…

免费实现网站HTTPS访问

HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是一种基于SSL协议的HTTP安全协议&#xff0c;旨在为客户端&#xff08;浏览器&#xff09;与服务器之间的通信提供加密通道&#xff0c;确保数据在传输过程中的保密性、完整性和身份验证。与传统的HTTP相比&a…

【数据结构与算法(C 语言)】栈的基本操作函数(动图演示) 及 栈的实际应用之一:进制转换

目录 1. 前言2. 结构及基本操作函数&#xff1a;2.1 栈的结构类型 Stack2.2 初始化栈 InitStack2.3 销毁栈 DestroyStack2.4 清空栈 ClearStack2.5 判断栈是否为空 StackEmpty2.6 获取stack的长度 StackLength2.7 获取栈顶元素 GetTop2.8 入栈 Push2.9 出栈 Pop2.10 访问元素2.…

COLING 2024: 复旦发布AoR,层级聚合推理突破大模型复杂推理上限

“三个臭皮匠&#xff0c;顶个诸葛亮&#xff1f;” “一个模型不行&#xff0c;那就再堆一个&#xff1f;” 过去当我们在处理复杂任务的时候&#xff0c;往往会考虑集成策略&#xff08;Ensembling Strategy&#xff09;&#xff0c;通过多个模型投票的方式&#xff0c;选出…

图形学初识--屏幕空间变换

文章目录 前言正文为什么需要屏幕空间变换&#xff1f;什么是屏幕空间变换&#xff1f;屏幕空间变换矩阵如何推导&#xff1f;问题描述步骤描述 结尾&#xff1a;喜欢的小伙伴点点关注赞哦! 前言 前面章节主要讲解了视图变换和投影变换&#xff0c;此时距离在屏幕空间显示也就…