Linux MySQL Connector/C++ 編程實例

本篇文章介紹如何在Linux平臺使用Connector/C++ 連接數據庫,假定MySQL已經安裝完成。如果還沒有安裝MySQL,請先安裝。MySQL版本:8.0.19

目錄

1. 安裝Connector/C++

2. 編寫代碼

3. 創建數據庫

4. 可能遇到的編譯問題解決方案

參考文檔:


示例是一個圖書館管理系統,擁有添加、刪除、修改、查詢功能。先看下實現效果圖:

在看具體代碼之前,先看下示例的設計文檔:

下面進入正式教程:

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

發佈了186 篇原創文章 · 獲贊 42 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章