C++ 连接Mysql 封装及基本管理

一,基本文件配置;
我用的时VS2017:
实验目的:
用Mysql为C提供的API封装出一个访问MySQL数据库的类。
引用API呢,简单说就是将MYSQL中include文件夹,libmysql.dll,libmysql.lib文件引入到项目中;最简单暴力的方法自然是通通给复制粘贴过来;
比较好的方法是在项目属性里配置好include目录、lib目录、libmysql.dll文件,最后把libmysql.dll文件给复制粘贴到和.cpp文件同级的目录下。只把前三个目录/文件引入配置中在运行时还是会报错找不到"libmysql.dll"文件。
在网上参考了很多教程,大多数的说法都是只配置好前三项,最后找到了一个比较靠谱一点的说法:
添加链接描述
是配置好前三项后再把libmysql.dll文件复制粘贴过来。
配置好后将解决方案平台改为“X64”
在这里插入图片描述
2,之后就可以开始运行了。
先进行一个运行测试:
当然主机名,和数据库要改成自己的

#include <iostream>
#include "mysql.h"using namespace std;int main()
{
    MYSQL conn;
    MYSQL_RES *res_set;
    MYSQL_ROW row;// 获得或初始化一个MYSQL结构
    mysql_init(&conn);// 连接一个MySQL服务器。
    if (!mysql_real_connect(&conn, "主机", "用户名", "密码", "数据库名", 3306, NULL, 0))
    {
        fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&conn));
    }
    else
    {
        fprintf(stdout, "Successfully connected to Database.\n");// 执行指定为一个空结尾的字符串的SQL查询。
        int status = mysql_query(&conn, "SELECT 1 + 2");// 检索一个完整的结果集合给客户。
        res_set = mysql_store_result(&conn);// 返回一个结果集合中的行的数量
        int count = mysql_num_rows(res_set); printf("No of rows = %d\n", count);while ((row = mysql_fetch_row(res_set)) != NULL)  // 从结果集合中取得下一行
        {
            // 返回最近查询的结果列的数量。
            for (int i = 0; i < mysql_num_fields(res_set); i++)
            {
                printf("%s \t", row[i] != NULL ? row[i] : "NULL");  // 第i列的值
            }
            printf("\n");
        }
    }// 关闭数据库
    mysql_close(&conn);
    
    return 0;
}

首先我们来认识一下要用到的函数:

    MYSQL conn;//定义一个Mysql结构
    MYSQL_RES *res_set;//mysql查询结果的集合
    MYSQL_ROW row;//其实实质上是一次数组
    mysql_init(MYSQL *);//初始化mysql结构
    mysql_real_connect(MYSQL *, "主机", "用户名", "密码", "数据库名", 3306, NULL, 0)//建立数据库连接
     mysql_query(MYSQL*, char *sql);//最基础的数据库查询
     mysql_store_result(MYSQL*);//将数据库中查询(mysql_query)得到的结果(集合)存放在MySQL_RES结构中,返回MYSQL_RES
     mysql_num_rows(MYSQL_RES);//返回int,受影响的含函数
    mysql_fetch_row(MYSQL_RES); //返回结果集(MYSQL_RES)的当前行的结果 ,返回MYSQL_ROW(数组);
    mysql_free_result(MYSQL_RES);//查询完成时调用
    mysql_close(MYSQL*);//关闭数据库连接
    mysql_error(MYSQL*);//返回错误信息;
    mysql_commit(MYSQL*);//提交事务在调用执行函数后

有5个类,一个接口

封装mysql类:

class Mysql {
public:
	Mysql();//默认构造函数,对MYSQL进行初始化
	Mysql( const char*host, const char*username, const char *password, const char *db);//带参数构造,对对象初始化,并调用连接函数连接数据库;
	virtual ~Mysql();//析构函数,实现mysql_close(&mysql);
	void Mysql_init();//自定义初始化函数,这里没怎么用
	int Mysql_execute(const char *sql);//自定义执行函数
	int Mysql_Query(const char *sql);//自定义查询函数
	void Mysql_Connect(const char*host, const char*username, const char *password, const char *db);//自定义连接函数,调用mysql_real_connection(^)
private:
	MYSQL mysql;//私有定义了MYSQL 结构对象
};
Mysql::Mysql() {
	mysql_init(&mysql);
}
void Mysql::Mysql_Connect(const char*host, const char*username, const char *password, const char *db) {
	if (mysql_real_connect(&mysql, host, username, password, db, 3306, NULL, 0)) {
		cout << "数据库连接成功!" << endl;
	}
	else {
		cout << " 数据库连接失败!" << endl;
		cout << "错误信息" << mysql_error(&mysql) << endl;
		exit(0);
	}
	cout << "_____________________" << endl;
}
Mysql::Mysql(const char*host, const char*username, const char *password, const char *db) {
	mysql_init(&mysql);
	Mysql_Connect(host, username, password, db);
}
Mysql::~Mysql() {
	mysql_close(&mysql);
	cout << "数据库关闭!" << endl;
}
int Mysql::Mysql_execute(const char *sql) {
	if (mysql_query(&mysql, sql)) {//查询函数,成功返回零,否则返回错误类型非零值
		cout << "更新失败:" << mysql_error(&mysql) << endl;
		return -1;
	}
	int arr = mysql_affected_rows(&mysql);//返回受影响的行数
	cout << "受影响的行数为:" << arr << endl;
	mysql_commit(&mysql);//完成事务
	return arr;
}
int Mysql::Mysql_Query(const char *sql) {
	if (mysql_query(&mysql, sql)) {
		cout << "查询失败:" << mysql_error(&mysql) << endl;
		return -1;
	}
	MYSQL_RES *RES = mysql_store_result(&mysql);//返回结果集
	MYSQL_ROW row;//定义

	int count = mysql_num_rows(RES);//返回结果集中行数
	cout << "查询到" << count << "条结果" << endl;
	cout << "学号\t" << "姓名" << endl;
	while ((row = mysql_fetch_row(RES)) != NULL) {//实质返回一次字节数组,并指向下一行
		for (int i = 0; i < mysql_num_fields(RES);i++) {//返回结果集列数
			if (row[i] != NULL) {
				cout << row[i] << "\t";
			}
			else {
				cout << NULL << " ";
			}
		}/*for*/
	}/*while*/
	cout << endl;
	mysql_free_result(RES);//一定要释放
	return count;
}
void Mysql::Mysql_init() {
	mysql_init(&mysql);
}

//定义基本的学生信息类,便于对数据库(对学生表)的数据管理
class student {
public:
	student();
	~student();
	int getsnum();
	string getsname();
	void setsnum(int snum);
	void setsname(string name);
private:
	int num;
	string name;
};
student::student() {

}
student::~student() {

}
void student::setsnum(int num) {
	this->num = num;
}
void student::setsname(string name) {
	this->name = name;
}
int student::getsnum() {
	return num;
}
string student::getsname() {
	return name;
}

class Istudentdao {
public:
	Istudentdao() {};//对构造函数先定义一下
	~Istudentdao() {};//同上
	virtual int insertStudent(student &stu)=0;//实现插入学生信息
	virtual int updateStudent(int sno, student&stu)=0;实现修改学生信息
	virtual int deleteStudent(int sno)=0;//实现删除学生信息
	virtual int selectStudent() = 0;//实现查询所有学生信息
	virtual int selectStudent(int sno) = 0;//重载实现查询特定学生信息
};
//这是一个纯接口,用来定义实现对数据库的操作函数
//这里就是具体实现了接口中的函数
class estudentdao :public Istudentdao {
public:
	estudentdao();
	~estudentdao();
	virtual int insertStudent(student &stu);
	virtual int updateStudent(int sno, student&stu);
	virtual int deleteStudent(int sno);
	virtual int selectStudent();
	virtual int selectStudent(int sno);
private:
	Mysql *ESTU;//对数据库的操作必须要有定义好的MYSQL
};
estudentdao::estudentdao() {
	ESTU = new Mysql("localhost", "root", "root", "sell");
}
estudentdao::~estudentdao() {

}
int estudentdao::insertStudent(student&stu) {
	string sql = "insert into student values(" + to_string(stu.getsnum()) + ",\'" + stu.getsname() + "'\)";//用student类定义好sql语句
	int ret = ESTU->Mysql_execute(sql.c_str());//c_str()返回的是临时指针
	return ret;
}
int estudentdao::deleteStudent(int sno) {
	string sql = "delete from student where sno=" + to_string(sno);
	int ret = ESTU->Mysql_execute(sql.c_str());//相同原理
	return ret;
}
int estudentdao::updateStudent(int sno, student&stu) {
	string sql = "update student set sno=" + to_string(stu.getsnum()) + ",sname=\'" + stu.getsname() + "'\ where sno=" + to_string(sno);
	int ret = ESTU->Mysql_execute(sql.c_str());//同上
	return ret;
}
int estudentdao::selectStudent() {
	string sql = "select *from student";
	int ret = ESTU->Mysql_Query(sql.c_str());//同上
	return ret;
}
int estudentdao::selectStudent(int sno) {
	string sql = "select " + to_string(sno) + "from student";
	int ret = ESTU->Mysql_Query(sql.c_str());//同上
	return ret;
}

//之前我们已经实现了接口,但这只是为了实现接口,重要的还是调用
class studentController {
public:
	studentController();
	studentController(Istudentdao *dao);//这里用接口作参数,依赖倒置,可以在管理层更灵活地调用修改执行方法,p:接口可能不止一种实现方法
	~studentController();
	int insertStudent(student &stu);
	int updateStudent(int sno, student&stu);
	int deleteStudent(int sno);
	int selectStudent();
	int selectStudent(int sno);//这些是基本上又实现了一遍
private:
	Istudentdao *dao;
	//之后依赖导致 Istudentdao *dao=new estudentdao(); 

};
studentController::studentController() {

}
studentController::studentController(Istudentdao *dao) {
	this->dao = dao;
}
studentController::~studentController() {
	if (dao != NULL) {
		delete dao;
	}
}
int studentController::insertStudent(student&stu) {
	return this->dao->insertStudent(stu);
}
int studentController::deleteStudent(int sno) {
	return this->dao->deleteStudent(sno);
}
int studentController::selectStudent() {
	return this->dao->selectStudent();
}
int studentController::selectStudent(int sno) {
	return this->dao->selectStudent(sno);
}
int studentController::updateStudent(int sno, student&stu) {
	return this->dao->updateStudent(sno, stu);
}

//最后的类,用来设计程序功能
class view {
public:
	view();
	~view();
	int viewAdd();
	int viewUpdate();
	int viewDelete();
	int viewSelect();
private:
	studentController *stucon;//对studentController依赖
};
view::view() {
	this->stucon = new studentController(new estudentdao());//用实现类来替代接口
}
view::~view() {
	if (!this->stucon) {
		delete this->stucon;
	}
}
int view::viewAdd() {
	int sno;
	string sname;
	cout << "请输入学号" << endl;
	cin >> sno;
	cout << "请输入姓名" << endl;
	cin >> sname;
	student stu;
	stu.setsnum(sno);
	stu.setsname(sname);
	this->stucon->insertStudent(stu);
	return 1;
}
int view::viewDelete(){
	int sno;
	cout << "请输入要删除哪一行" << endl;
	cin >> sno;
	this->stucon->deleteStudent(sno);
	return 1;
}
int view::viewUpdate() {
	int sno;//修改前学生的学号
	student stu;
	cout << "输入修改前的学号(四位数):";
	cin >> sno;
	int sno_1;
	string name_1;
	cout << "输入修改后的学号(四位数):";
	cin >> sno_1;
	cout << "输入修改后的姓名:";
	cin >> name_1;
	stu.setsname(name_1);
	stu.setsnum(sno_1);
	this->stucon->updateStudent(sno, stu);
	return 1;
}
int view::viewSelect() {
	int sno;
	cout << "请输入要查询的学号,按0查询所有" << endl;
	cin >> sno;
	if (0==sno) {
		this->stucon->selectStudent();
	}
	else {
		this->stucon->selectStudent(sno);
	}
	return 1;
}

int main() {
	view view1;
	int flag = 1;
	int switch_on;
	while (1 == flag) {
		cout << "1.添加学生" << endl;
		cout << "2.更新学生" << endl;
		cout << "3.删除学生" << endl;
		cout << "4.查询学生" << endl;
		cout << "5.退出" << endl;
		cout << "输入:";
		cin >> switch_on;
		switch (switch_on)
		{
		case 1:
			view1.viewAdd();
			break;
		case 2:
			view1.viewUpdate();
			break;
		case 3:
			view1.viewDelete();
			break;
		case 4:
			view1.viewSelect();
			break;
		case 5:
			flag = 0;
			break;
		default:
			break;
		}
	}
	return 0;
}
//主方法:用来完成;

至此,C++ 连接Mysql 封装及基本管理的具体实现就结束了;
从这些函数中可以更清楚地了解到,c++的面向对象编程是怎样环环相扣的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值