1 获取连接Session

1.1 构造session对象

X DevAPI session是建立在传统mysql连接基础上的高层次会话,使用MySql X protocol,支持DevAPI中全部操作和部分SQL语言功能。

我们可以直接传递参数构造一个session对象,示例如下:

  1. #include <iostream>
  2. #include <mysqlx/xdevapi.h>
  3. using namespace std;
  4. using namespace mysqlx;
  5. int main()
  6. {
  7. //利用大括号,session在括号结束时自动close连接并释放资源
  8. {
  9. Session sess("localhost", 33060, "barret", "newpasswd");
  10. Schema db = sess.getSchema("world_x"); //获取数据库
  11. // or Schema db(sess, "test");
  12. }
  13. }

也可以通过SessionSetting设置参数,再创建session对象:

  1. SessionSettings settings(SessionOption::HOST,"localhost",SessionOption::PORT, 33060);
  2. settings.set(SessionOption::USER, "barret");
  3. settings.set(SessionOption::PWD, "newpasswd");
  4. Session mySession(settings);
  5. Schema myDb= mySession.getSchema("world_x");

我们可以用URI的格式尝试连接多个server,最后会返回按优先级排列的连接成功的session,URI格式如下:

  1. user:password@[(address=[host]:[port], priority=value), (address=[host]:[port], priority=value) ..]

1.2 connection pooling

X DevAPI支持connection pooling,可以避免反复的创建释放数据库连接。connection pool的生命周期依赖Client对象,当Client对象析构时,pool就不复存在了。
pool的配置如下:

Option Meaning Default
enabled Connection pooling enabled. When the option is set to false, a regular, non-pooled connection is returned, and the other connection pool options listed below are ignored. true
maxSize The maximum number of connections allowed in the pool 25
maxIdleTime The maximum number of milliseconds a connection is allowed to idle in the queue before being closed. A zero value means infinite. 0
queueTimeout The maximum number of milliseconds a request is allowed to wait for a connection to become available. A zero value means infinite 0

使用示例如下:

  1. int main()
  2. {
  3. /*
  4. ( "mysqlx://user:password@host_name/db_name",
  5. ClientOption::POOLING, true,
  6. ClientOption::POOL_MAX_SIZE, max_connections,
  7. ClientOption::POOL_QUEUE_TIMEOUT, std::chrono::seconds(100),
  8. ClientOption::POOL_MAX_IDLE_TIME, std::chrono::microseconds(1)
  9. */
  10. Client cli("mysqlx://barret:shidandan1230@localhost/world_x", ClientOption::POOL_MAX_SIZE, 7);
  11. Session sess = cli.getSession();
  12. // use Session sess as usual
  13. cli.close(); // close all Sessions
  14. }

2 获取数据库对象Schema

通过session的函数getSchema()getDefaultSchema()可以获取到Schema对象。可以把Schema当作是DB对象,Schema是访问操作数据表的基本结构。

简单示例如下:

  1. int main()
  2. {
  3. Session sess("localhost", 33060, "barret", "newpasswd");
  4. //获取所有的数据库并打印name
  5. std::list<Schema> schemaList = sess.getSchemas();
  6. cout << "Available schemas in this session:" << endl;
  7. for (Schema schema : schemaList)
  8. {
  9. cout << schema.getName() << endl;
  10. }
  11. Schema db = sess.getSchema("world_x"); //获取指定数据库
  12. Table table = db.getTable("city");//获取表
  13. cout<<"row count of city table is "<<table.count()<<endl;
  14. }

3 执行原始SQL语句

通过session.sql()函数,我们可以执行原始的SQL语句:

  1. //使用session的sql函数,执行原始SQL语句
  2. #include <iostream>
  3. #include <mysqlx/xdevapi.h>
  4. using namespace std;
  5. using namespace mysqlx;
  6. int main()
  7. {
  8. try
  9. {
  10. Session sess("localhost", 33060, "barret", "shidandan1230");
  11. cout << "Session accepted, creating collection..." << endl;
  12. sess.sql("use world_x").execute(); //使用url不需要这句
  13. //执行一个select语句并打印结果
  14. RowResult rs = sess.sql("SELECT ID, Name, CountryCode FROM city where ID <10").execute();
  15. for (auto it = rs.begin(); it != rs.end(); ++it)
  16. {
  17. cout << (*it).get(0).get<int>() << " ";
  18. cout << (*it).get(1).get<std::string>() << " ";
  19. cout << (*it).get(2).get<std::string>();
  20. cout << endl;
  21. }
  22. }
  23. catch (const Error &e)
  24. {
  25. cout << e.what() << endl;
  26. }
  27. return 0;
  28. }

4 CRUD基本函数

DevAPI提供了如下函数,用于对collection和table执行CRUD操作:

Operation Document Relational
Create Collection.add() Table.insert()
Read Collection.find() Table.select()
Update Collection.modify() Table.update()
Delete Collection.remove() Table.delete()

image.png
比如我们可以用select函数查询city table代替上一节中的原始sql示例:

  1. //使用API提供的函数读取表内容,这里不是用原始SQL
  2. #include <iostream>
  3. #include <mysqlx/xdevapi.h>
  4. using namespace std;
  5. using namespace mysqlx;
  6. int main()
  7. {
  8. try
  9. {
  10. Session sess("localhost", 33060, "barret", "shidandan1230");
  11. cout << "Session accepted, creating collection..." << endl;
  12. Schema db = sess.getSchema("world_x");
  13. Table city = db.getTable("city"); //获取数据表
  14. RowResult rs = city.select("ID", "Name", "CountryCode").where("ID < 10").execute();
  15. for (auto it = rs.begin(); it != rs.end(); ++it)
  16. {
  17. cout << (*it).get(0).get<int>() << " ";
  18. cout << (*it).get(1).get<std::string>() << " ";
  19. cout << (*it).get(2).get<std::string>();
  20. cout << endl;
  21. }
  22. }
  23. catch (const Error &e)
  24. {
  25. cout << e.what() << endl;
  26. }
  27. return 0;
  28. }

Note: 默认的execute是同步操作,会一直阻塞等待SQL的执行结果。我们可以通过callbacks, Promises或explicitly waiting来实现异步执行。但是C++API并不支持异步,可以使用C#或java实现异步。

5 参数绑定

在使用CRUD各个函数时,我们可以使用bind()函数绑定SQL中的参数,这样就不需要费心的组装SQL字符串了。
对每一个参数,在CRUD函数中使用:name形式指定参数名,并在bind函数中通过name指定value(一般bind只能绑定一个参数,不需要考虑顺序)。
示例如下:

  1. try
  2. {
  3. Session sess("localhost", 33060, "barret", "shidandan1230");
  4. cout << "Session accepted, creating collection..." << endl;
  5. Schema db = sess.getSchema("world_x");
  6. Table city = db.getTable("country"); //获取数据表
  7. //使用1,bind绑定参数
  8. // RowResult rs = city.select().where("Name = :param1").bind("param1", "China").execute();
  9. //使用2,可以通过bind和execute将一个操作重复执行多次:
  10. auto statement = city.select().where("Name = :param1");
  11. RowResult rs = statement.bind("param1", "China").execute();
  12. //打印结果
  13. rs = statement.bind("param1", "United States").execute();
  14. //打印结果
  15. }

6 查询结果处理

image.png