Cocos2d-x數據持久化-查詢數據

數據查詢通常會帶有查詢條件,這可使用SQL語句的where子句實現,可是在程序中須要動態綁定參數給where子句。查詢數據的具體操做步驟以下所示。
(1) 使用sqlite3_open函數打開數據庫。
(2) 使用sqlite3_prepare_v2函數預處理SQL語句。
(3) 使用sqlite3_bind_text函數綁定參數。
(4) 使用sqlite3_step函數執行SQL語句,遍歷結果集。
(5) 使用sqlite3_column_text等函數提取字段數據。 
(6) 使用sqlite3_finalize和sqlite3_close函數釋放資源。


NoteDAO.cpp中的NoteDAO::findById是按照主鍵查詢數據函數,相關代碼以下:html

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. ValueMap NoteDAO::findById(string pDate)  
  2. {  
  3.     //初始化數據庫  
  4.     initDB();  
  5.     sqlite3* db= NULL;  
  6.     ValueMap dict ;  
  7.   
  8.   
  9.     string path = dbDirectoryFile();  
  10.   
  11.   
  12.     if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) {                             ①  
  13.         sqlite3_close(db);  
  14.         CCASSERT(false, "DB open failure.");  
  15.     } else {  
  16.         string qsql = "SELECT cdate,content FROM Note where cdate =?";  
  17.         sqlite3_stmt *statement;  
  18.         //預處理過程  
  19.         if (sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL) == SQLITE_OK) {      ②  
  20.   
  21.   
  22.             //綁定參數開始  
  23.             sqlite3_bind_text(statement, 1, pDate.c_str(), -1, NULL);                       ③  
  24.   
  25.   
  26.             //執行  
  27.             if (sqlite3_step(statement) == SQLITE_ROW) {                            ④  
  28.   
  29.   
  30.                 char *cdate = (char *)sqlite3_column_text(statement, 0);                    ⑤  
  31.                 char *content = (char *)sqlite3_column_text(statement, 1);  
  32.   
  33.   
  34.                 dict["date"] = Value(cdate);                                          
  35.                 dict["content"] = Value(content);                                     
  36.             }  
  37.         }  
  38.         sqlite3_finalize(statement);                                            ⑥  
  39.         sqlite3_close(db);                                                  ⑦  
  40.     }  
  41.     return dict;  
  42. }  



該函數執行了6個步驟,其中第(1)個步驟如代碼第①行所示,它與建立數據庫的第一個步驟同樣,這裏就再也不介紹了。
第(2)個步驟如代碼第②行所示,語句sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL)是預處理SQL語句。預處理的目的是將SQL編譯成二進制代碼,提升SQL語句的執行速度。sqlite3_prepare_v2函數的第三個參數表示SQL字符串的長度,-1表示所有SQL字符串。第四個參數是sqlite3_stmt指針的地址,它是語句對象,經過語句對象能夠執行SQL語句,第五個參數是SQL語句沒有執行的部分語句。 
第(3)個步驟如代碼第③行所示,語句sqlite3_bind_text(statement, 1, pDate.c_str(), -1, NULL)是綁定SQL語句的參數,其中第一個參數是statement指針,第二個參數爲序號(從1開始),第三個參數爲字符串值,第四個參數爲字符串長度,第五個參數爲一個函數指針。若是SQL語句中帶有問號,則這個問號(它是佔位符)就是要綁定的參數,示例代碼以下所示:
string qsql = "SELECT cdate,content FROM Note where cdate =?";
第(4)個步驟爲使用sqlite3_step(statement)執行SQL語句,如代碼第④行所示。若是sqlite3_step函數返回int類型(即等於SQLITE_ROW),則說明還要其它行數據沒有遍歷。
第(5)個步驟爲提取字段數據,如代碼第⑤行所示,它使用sqlite3_column_text(statement, 0)函數讀取字符串類型的字段。須要說明的是,sqlite3_column_text函數的第二個參數用於指定select字段的索引(從0開始)。讀取字段函數的選擇與字段類型有關係,SQLite3中相似的經常使用函數還有: 
sqlite3_column_blob()
sqlite3_column_double()
sqlite3_column_int()
sqlite3_column_int64()
sqlite3_column_text()
sqlite3_column_text16()
關於其它API,讀者能夠參考http://www.sqlite.org/cintro.html。
第(6)個步驟是釋放資源,與建立數據庫過程不一樣。使用sqlite3_close函數關閉數據庫(見第⑦行)以前,還要使用sqlite3_finalize函數釋放語句對象statement,見代碼第⑥行所示。
NoteDAO.cpp中的NoteDAO::findAll()是查詢全部數據函數,相關代碼以下:
ValueVector NoteDAO::findAll()sql

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. {  
  2.     //初始化數據庫  
  3.     initDB();  
  4.     sqlite3* db= NULL;  
  5.   
  6.   
  7.     string path = dbDirectoryFile();  
  8.     ValueVector listData;  
  9.   
  10.   
  11.     if (sqlite3_open(path.c_str(), &db) != SQLITE_OK) {  
  12.         sqlite3_close(db);  
  13.         CCASSERT(false, "DB open failure.");  
  14.     } else {  
  15.         string qsql = "SELECT cdate,content FROM Note";  
  16.         sqlite3_stmt *statement;  
  17.         //預處理過程  
  18.         if (sqlite3_prepare_v2(db, qsql.c_str(), -1, &statement, NULL) == SQLITE_OK) {  
  19.             //執行  
  20.             while (sqlite3_step(statement) == SQLITE_ROW) {  
  21.   
  22.   
  23.                 char *cdate = (char *)sqlite3_column_text(statement, 0);  
  24.                 char *content = (char *)sqlite3_column_text(statement, 1);  
  25.   
  26.   
  27.                 ValueMap dict ;  
  28.                 dict["date"] = Value(cdate);  
  29.                 dict["content"] = Value(content);  
  30.   
  31.   
  32.                 listData.push_back(Value(dict));  
  33.             }  
  34.         }  
  35.         sqlite3_finalize(statement);  
  36.         sqlite3_close(db);  
  37.     }  
  38.     return listData;  
  39. }  


查詢全部數據函數與按照主鍵查詢數據函數相似,區別在於本函數沒有查詢條件不須要綁定參數。遍歷的時候使用while循環語句,不是if語句:數據庫

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. while (sqlite3_step(statement) == SQLITE_ROW) {  
  2.     ……  
  3. }  





爲了可以調用NoteDAO中查詢函數findAll (),咱們須要在HelloWorldScene場景中調用。HelloWorldScene.cpp主要代碼以下:微信

[html]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. void HelloWorld::OnClickMenu5(Ref* pSender)  
  2. {  
  3.     auto arry = NoteDAO::findAll();                                         ①  
  4.   
  5.   
  6.     for (auto& v: arry)  
  7.     {  
  8.         log("-----------------");  
  9.         ValueMap row = v.asValueMap();                                      ②  
  10.         string date = row["date"].asString();                                       ③  
  11.         string content = row["content"].asString();                                 ④  
  12.   
  13.   
  14.         log("===>date: : %s", date.c_str());  
  15.         log("===>content: : %s", content.c_str());  
  16.     }  
  17.   
  18.   
  19. }  



HelloWorld::OnClickMenu5函數是玩家點擊Read Data菜單時候回調的函數。其中代碼第①行是調用NoteDAO中查詢全部函數findAll (),第②行代碼是把從列表中取出的元素v,轉換爲ValueMap字典類型。第③行代碼是從字典中取值date數據。第④行代碼是從字典中取值content數據。函數

 

 

更多內容請關注國內第一本Cocos2d-x 3.2版本圖書《Cocos2d-x實戰:C++卷》
本書交流討論網站: http://www.cocoagame.net
更多精彩視頻課程請關注智捷課堂Cocos課程: http://v.51work6.com
歡迎加入Cocos2d-x技術討論羣:257760386
歡迎關注智捷iOS課堂微信公共平臺

相關文章
相關標籤/搜索