本篇文章介紹如何在Linux平臺使用Connector/C++ 連接數據庫,假定MySQL已經安裝完成。如果還沒有安裝MySQL,請先安裝。MySQL版本:8.0.19
目錄
示例是一個圖書館管理系統,擁有添加、刪除、修改、查詢功能。先看下實現效果圖:
在看具體代碼之前,先看下示例的設計文檔:
下面進入正式教程:
1. 安裝Connector/C++
下載地址(https://dev.mysql.com/downloads/connector/cpp/)。
下載解壓完成後,如下圖:
lib64存放庫文件,include存放頭文件。
2. 編寫代碼
新建library目錄。然後在該目錄下新建三個文件。library_main.cpp, library_sql.h, library_book.h Makefile 。代碼如下:
library_main.cpp
/*
* Desc: Linux c++ MySQL 示例,圖書館管理系統,主程序
* Author: mason
* Date: 20200203
*/
#include "library_book.h"
#include "library_sql.h"
#define LIBRARY_ADD_BOOK 1 // 添加
#define LIBRARY_DELETE_BOOK 2 // 刪除
#define LIBRARY_UPDATE_BOOK 3 // 修改
#define LIBRARY_QUERY_BOOK 4 // 查詢
#define LIBRARY_QUIT 5 // 退出
// MySQL單例類靜態變量初始化
sql::Driver* sql_loader::driver = nullptr;
sql::Connection* sql_loader::con = nullptr;
sql::Statement* sql_loader::stmt = nullptr;
sql::ResultSet* sql_loader::res = nullptr;
bool sql_loader::init = false;
// 系統使用說明
void Usage()
{
cout<<"\n歡迎使用圖書管理系統\n"
"1:添加圖書\n"
"2:刪除圖書\n"
"3:修改圖書\n"
"4:查詢圖書\n"
"5:退出系統\n"
<<endl;
return ;
}
// 讀取圖書信息
void ReadBook(Book &new_book)
{
cout<<"請輸入添加的書名:";
cin>>new_book.book_name;
cout<<"請輸入作者:";
cin>>new_book.author;
//cout<<"[DEBUG]"<<author<<endl;
cout<<"請輸入價格:";
cin>>new_book.price;
cout<<"請輸入數量:";
cin>>new_book.quantity;
return ;
}
int main()
{
bool is_quit = false;
int op_code = -1, book_id;
string book_name, author;
unsigned int price, quantity;
Book new_book;
vector<Book> book_list;
// 主循環
while (!is_quit)
{
Usage();
cout<<"請輸入你的選擇:";
cin>>op_code;
switch (op_code)
{
// 添加操作
case LIBRARY_ADD_BOOK:
// 讀取圖書信息
ReadBook(new_book);
sql_loader::add(new_book);
break;
// 刪除操作
case LIBRARY_DELETE_BOOK:
sql_loader::delete_book();
break;
// 修改操作
case LIBRARY_UPDATE_BOOK:
cout<<"請輸入待修改的編號:";
cin>>new_book.id;
ReadBook(new_book);
sql_loader::update(new_book);
break;
// 查詢操作
case LIBRARY_QUERY_BOOK:
sql_loader::query(book_list);
// 打印查詢結果
cout << "------------- 查詢開始 ----------------" <<endl;
for (auto &iter : book_list)
{
cout <<"編號: "<< iter.id << endl;
cout <<"書名: "<< iter.book_name << endl;
cout <<"作者: "<< iter.author << endl;
cout <<"數量: "<< iter.quantity << endl;
cout <<"價格: "<< iter.price << endl;
cout << "-----------------------------" <<endl;
}
cout << "------------- 查詢結束 ----------------" <<endl;
// 清空上次查詢結果
book_list.erase(book_list.begin(), book_list.end());
break;
// 退出系統
case LIBRARY_QUIT:
is_quit = true;
break;
default:
cout<<"未識別的操作:"<<op_code<<endl;
break;
}
}
cout<<"感謝使用"<<endl;
return 0;
}
library_book.h
/*
* Desc: Linux c++ MySQL 示例,圖書館管理系統,圖書類
* Author: mason
* Date: 20200203
*/
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Book
{
public:
int id; // 圖書編號
string book_name; // 書名
string author; // 作者
unsigned int price; // 價格
unsigned int quantity; // 數量
public:
// 默認構造函數
Book(){}
// 含參構造函數
Book(string book_name, string author, int price, int quantity, int book_id = 0):book_name(book_name),author(author),
price(price),quantity(quantity), id(book_id){}
// 析構函數
~Book(){}
};
library_sql.h
/*
* Desc: Linux c++ MySQL 示例,圖書館管理系統,MySQL單例
* Author: mason
* Date: 20200203
*/
#pragma once
#include <vector>
#include "library_book.h"
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#define SQL_QUERY_ALL 0 // 查詢所有
#define SQL_QUERY_BY_AUTHOR 1 // 查詢作者
#define SQL_QUERY_BY_ID 2 // 查詢編號
#define SQL_QUERY_BY_BOOK_NAME 3 // 查詢書名
#define SQL_DELETE_ALL 0 // 刪除所有
#define SQL_DELETE_BY_AUTHOR 1 // 刪除作者
#define SQL_DELETE_BY_ID 2 // 刪除編號
#define SQL_DELETE_BY_BOOK_NAME 3 // 刪除書名
using namespace std;
class sql_loader
{
public:
static sql::Driver *driver;
static sql::Connection *con;
static sql::Statement *stmt;
static sql::ResultSet *res;
static bool init;
// sql 初始化
static void sql_loader_init()
{
if (sql_loader::init)
{
cout<<"sql 已經完成初始化"<<endl;
return ;
}
/* Create a connection */
driver = get_driver_instance();
// 密碼和用戶名
con = driver->connect("tcp://127.0.0.1:3306", "root", "123456");
/* Connect to the MySQL test database ,數據庫名*/
con->setSchema("library");
init = true;
cout<<"sql 初始化成功"<<endl;
return ;
}
// 添加圖書
static void add(Book &new_book)
{
// SQL初始化
sql_loader_init();
// 創建並構造sql語句,用完後手動刪除
stmt = con->createStatement();
string sql_cmd = "INSERT INTO books(name, author, price, quantity) VALUES ('";
sql_cmd.append(new_book.book_name);
sql_cmd.append("','");
sql_cmd.append(new_book.author);
sql_cmd.append("', ");
sql_cmd.append(to_string(new_book.price));
sql_cmd.append(", ");
sql_cmd.append(to_string(new_book.quantity));
sql_cmd.append(")");
cout<<"insert cmd : "<<sql_cmd<<endl;
try{
stmt->execute(sql_cmd);
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line "
<< __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
// 刪除資源
delete stmt;
return ;
}
// 修改圖書
static void update(Book& new_book)
{
// SQL初始化
sql_loader_init();
// 創建並構造sql語句,用完後手動刪除
stmt = con->createStatement();
string sql_cmd = "update books set name='";
sql_cmd.append(new_book.book_name);
sql_cmd.append("', author='");
sql_cmd.append(new_book.author);
sql_cmd.append("', price=");
sql_cmd.append(to_string(new_book.price));
sql_cmd.append(", quantity=");
sql_cmd.append(to_string(new_book.quantity));
sql_cmd.append(" where id=");
sql_cmd.append(to_string(new_book.id));
cout<<"update cmd : "<<sql_cmd<<endl;
try{
stmt->execute(sql_cmd);
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line "
<< __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
// 釋放資源
delete stmt;
return ;
}
// 刪除圖書
static void delete_book()
{
int op_code = -1, book_id;
string author, book_name;
string sql_cmd = "delete from books";
cout<<"請輸入刪除方式:\n"
"0: 刪除所有圖書\n"
"1: 刪除指定作者\n"
"2: 刪除指定編號\n"
"3: 刪除指定圖書"<<endl;
cin>>op_code;
switch (op_code)
{
case SQL_DELETE_ALL:
break;
case SQL_DELETE_BY_AUTHOR:
cout<<"請輸入要刪除的作者:";
cin>>author;
sql_cmd.append(" where author='");
sql_cmd.append(author);
sql_cmd.append("'");
break;
case SQL_DELETE_BY_ID:
cout<<"請輸入要刪除的編號:";
cin>>book_id;
sql_cmd.append(" where id=");
sql_cmd.append(to_string(book_id));
break;
case SQL_DELETE_BY_BOOK_NAME:
cout<<"請輸入要刪除的書名:";
cin>>book_name;
sql_cmd.append(" where name='");
sql_cmd.append(book_name);
sql_cmd.append("'");
break;
default:
cout<<"不存在 "<<op_code<<" 對應的刪除方式,刪除失敗"<<endl;
return ;
}
cout<<"delete cmd : "<<sql_cmd<<endl;
// 初始化SQL
sql_loader_init();
// 創建並構造sql語句,用完後手動刪除
stmt = con->createStatement();
try{
// 執行SQL語句
stmt->execute(sql_cmd);
// 釋放資源
delete stmt;
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line "
<< __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
return ;
}
// 查詢圖書
static void query(vector<Book>& book_list)
{
int op_code = -1, book_id;
string author, book_name;
string sql_cmd = "select id, name, author, quantity, price from books";
cout<<"請輸入查詢方式:\n"
"0: 查詢所有\n"
"1: 查詢作者\n"
"2: 查詢編號\n"
"3: 查詢書名"<<endl;
cin>>op_code;
switch (op_code)
{
case SQL_QUERY_ALL:
break;
case SQL_QUERY_BY_AUTHOR:
cout<<"請輸入要查詢的作者:";
cin>>author;
sql_cmd.append(" where author='");
sql_cmd.append(author);
sql_cmd.append("'");
break;
case SQL_QUERY_BY_ID:
cout<<"請輸入要查詢的編號:";
cin>>book_id;
sql_cmd.append(" where id=");
sql_cmd.append(to_string(book_id));
break;
case SQL_QUERY_BY_BOOK_NAME:
cout<<"請輸入要查詢的書名:";
cin>>book_name;
sql_cmd.append(" where name='");
sql_cmd.append(book_name);
sql_cmd.append("'");
break;
default:
cout<<"不存在 "<<op_code<<" 對應的查詢方式,查詢失敗"<<endl;
return ;
}
cout<<"query cmd : "<<sql_cmd<<endl;
// 初始化SQL
sql_loader_init();
// 創建並構造sql語句,用完後手動刪除
stmt = con->createStatement();
try{
// 執行查詢
res = stmt->executeQuery(sql_cmd);
while (res->next()) {
/* Access column data by alias or column name */
cout << res->getInt("id") << res->getString("name") << res->getString("author") << res->getInt("quantity") << endl;
book_list.push_back(Book(res->getString("name"), res->getString("author"), res->getInt("price"), res->getInt("quantity"), res->getInt("id")));
/* Access column data by numeric offset, 1 is the first column */
//cout << res->getString(1) << endl;
}
// 資源釋放
delete res;
delete stmt;
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line "
<< __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
return ;
}
private:
sql_loader(){}
};
Makefile,編譯路徑根據實際路徑做調整。
default:
g++ -std=c++11 -I /data/home/code/github/cpp-test/mysql/include/jdbc -L /data/home/code/github/cpp-test/mysql/lib64 library_main.cpp -o app -lmysqlcppconn
clean:
rm -rf app
3. 創建數據庫
// 創建數據庫
create database library;
// 創建圖書表
create table books (
id int not null auto_increment,
name varchar(1024) not null,
author varchar(1024) not null,
price int not null default 0,
quantity int not null default 1,
primary key(id)
)DEFAULT CHARACTER SET = utf8;
4. 可能遇到的編譯問題解決方案
1. jdbc/mysql_connection.h:37:32: fatal error: boost/shared_ptr.hpp: No such file or directory
解決方式是安裝boost-devel,yum安裝命令如下,ubuntu或者其它平臺請自行搜索。
yum install boost-devel
2. # ERR: Host '127.0.0.1' is not allowed to connect to this MySQL server (MySQL error code: 1130, SQLState: HY000 )
無法連接MySQL,先查看本地msyqld是否允許以及能否登陸,都正常可能是權限問題,參考這篇博客:
https://blog.csdn.net/eric_sunah/article/details/18567091
參考文檔:
1. https://docs.oracle.com/cd/E17952_01/connector-cpp-1.1-en