官方文档:
https://dev.mysql.com/doc/dev/connector-cpp/latest/
mysql client的c/c++ api一共三个版本:
这里使用最后一个JDBC的版本,该版本按照Java版本JDBC进行编写,实现了80%Java版本JDBC的接口,使用该版本是因为用Java JDBC的人多,容易解决搜到疑难杂症的解决方法。
接口介绍及代码
环境:已安装mysql server在本机
表中右部分数据:
/* 现有数据库testdatabase中user表
- ---- + ---------- + ---------------- + ------------ + ---------- - ±----- +
| id | username | email | birthdate | is_active | name |
±— + ---------- + ---------------- + ------------ + ---------- - ±----- +
| 1 | a | 123456@xxx.com | 2000 - 01 - 01 | 1 | NULL |
| 2 | b | 123456@xxx.com | 2000 - 01 - 01 | 1 | NULL |
| 3 | c | 123456@xxx.com | 2000 - 01 - 01 | 1 | NULL |
| 4 | 3 | 123456@xxx.com | 2000 - 01 - 01 | 1 | NULL |
±— + ---------- + ---------------- + ------------ + ---------- - ±----- +
*/
#include "jdbc/mysql_driver.h"
#include "jdbc/mysql_connection.h"
#include "jdbc/cppconn/driver.h"
#include "jdbc/cppconn/connection.h"
#include "jdbc/cppconn/statement.h"
#include "jdbc/cppconn/prepared_statement.h"
#include "jdbc/cppconn/resultset.h"
#include "jdbc/cppconn/metadata.h"
#include "jdbc/cppconn/resultset_metadata.h"
#include "jdbc/cppconn/exception.h"
#include "jdbc/cppconn/warning.h"
#include "mysql/jdbc.h"
#include <vector>
#include <chrono>
using namespace std;
#define DEFAULT_URI "tcp://127.0.0.1:3306"
#define EXAMPLE_USER "user"
#define EXAMPLE_PASS "password"
#define EXAMPLE_DB "testdatabase"
int main()
{
const char* url = DEFAULT_URI;
const string user(EXAMPLE_USER);
const string pass(EXAMPLE_PASS);
const string database(EXAMPLE_DB);
// 获取驱动 该驱动不要在代码中显式的析构 connector会自动处理的
// get_driver_instance也不是线程安全的 多线程使用要加锁 确保多个线程不会同时执行该函数
sql::Driver* driver = sql::mysql::get_driver_instance();
/* 连接数据库 */
cout << "Creating session on " << url << " ..."
<< endl << endl;
// sql::Connection需要程序员来负责析构 因此使用智能指针
std::unique_ptr< sql::Connection > con(driver->connect(url, user, pass));
if (!con->isValid()) { // checks whether the connection is alive
cout << "connect falied, reconnected" << endl;
con->reconnect(); // reconnects if the connection has gone down
}
else {
cout << "connect success" << endl;
}
/* 查询数据库 */
con->setSchema(database); // 选择数据库
std::unique_ptr< sql::Statement > stmt(con->createStatement()); // sql::Statement 用于执行sql语句等
// sql::Statement执行查询语句 sql::ResultSet中保存查询结果
std::unique_ptr< sql::ResultSet > res(stmt->executeQuery("SELECT * FROM users"));
/* 如下方法用于执行一些简单的查询
* sql::Statement::execute()
* sql::Statement::executeQuery() : if your query does not return a result set or if your query returns more than one result set.
* sql::Statement::executeUpdate()
*/
// 注意sql::Statement 和 sql::ResultSet 需要析构 因此采用了unique_ptr
/* 获取查询结果 */
try {
while (res->next()) {
int id = res->getInt(1); // 1为列数 从1开始算 但要保查询的结果中有该列 否则抛出异常 getInt用于将该列的值以int方式返回
string username = res->getString("username"); // 也可用字段的名称获取该列的值 getString返回std::string
bool isActive = res->getBoolean("is_active");
cout << id << " " << username << " " << (isActive ? "true" : "false") << endl;
}
}
catch (sql::SQLException& e) { // 派生关系 std::runtime_error->sql::SQLException
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
/* 开启事务 */
try {
con->setAutoCommit(false); // 关闭自动提交 即不会在每次执行完sql语句后就commit
string sql1 = "INSERT INTO users VALUES(10, 'Lucy1', '123456@xxx.com', '2000-02-02', true, '')";
string sql2 = "INSERT INTO users VALUES(11, 'Lucy2', '123456@xxx.com', '2000-02-02', true, '')";
stmt->executeUpdate(sql1);
stmt->executeUpdate(sql2);
con->commit();
}
catch (sql::SQLException& e) {
std::cout << "update failed : " << e.what() << std::endl;
con->rollback(); // 执行出错就回滚
}
return 0;
}
执行sql语句的三个接口:
1、executeUpdate 执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,该方法返回 int 类型的值,显示数据库中改变的行数
2、executeQuery 方法,用于执行查询语句的方法,执行后返回代表查询结果的ResultSet对象,在ResultSet对象中存储查询产生的结果。
ResultSet.next()方法是判断这个结果集中下一行是否有内容,如果有内容,返回true,逐行判断,ResultSet.get×××(参数)方法是用来获取这一行的某一个字段,这里的‘参数’,可以是字段的名字也可以相对来说字段名的位置(从1开始)
2、execute返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等。
如果返回值为true ,则用 statement.getResultSet();方法返回一个ResultSet对象,就可以对ResultSet对象遍历输出,查看结果。