正在物色node上面的輕量級嵌入式數據庫,做爲嵌入式數據庫的表明,sqlite無疑是個理想的選擇方案。npm上集成sqlite的庫主要有兩個——sqlite3和realm。java
realm是一個理想的選擇方案,它最初是爲移動app設計的,在node也能夠運行的,可是不支持Windows系統。sqlite3是一個專爲nodejs設計的,在nodejs上面生態更健壯,所以最終選擇sqlite3。node
sqlite3幾乎支持全部版本的nodejs,同時也能夠和nwjs集成。linux
安裝
基於npm安裝git
這樣除了安裝完sqlite3的npm包,最主要的是也裝完了sqlite數據庫,由於sqlite是嵌入式數據庫,嵌入到客戶端中。sqlite3使用node-pre-gyp爲各個平臺下載指定的預編譯的二進制文件。若是沒法下載到預編譯的二進制文件,sqlite3將使用node-gyp和源代碼來構建擴展。github
這個過程出現兩個的庫——node-pre-gyp和node-gyp。他們到底是什麼呢?sql
node-gyp是一個跨平臺的命令行工具,用於編譯C++編寫的nodejs擴展,首先gyp是爲Chromium項目建立的項目生成工具,能夠從平臺無關的配置生成平臺相關的Visual Studio、Xcode、Makefile的項目文件,node-gyp就是將其集成到nodejs中。由於linux的二進制分發快平臺作的並很差,全部npm爲了方便乾脆就直接源碼分發,用戶裝的時候再現場編譯。不過對有些項目二進制分發就比源碼分發簡單多了,因此還有個node-pre-gyp來直接二進制擴展的分發。數據庫
二者區別在於node-gyp是發佈擴展的源碼,而後安裝時候編譯;node-pre-gyp是直接發佈編譯後的二級制形式的擴展。npm
和sqlite3同樣的須要基於node-gyp安裝的npm模塊也有不少,好比node-sass等,都是發佈源代碼,而後編譯安裝。json
基礎api
sqlite3的api都是基於函數回調的,由於nodejs中沒有像java的jdbc那種官方的數據庫客戶端接口,所以每一個數據庫的api都不同,這裏簡單介紹幾個sqlite3重要的api。api
新建並打開數據庫
該方法返回一個自動打開的數據庫對象,參數:
filename:有效值是一個文件名,如:「mydatebase.db」,數據庫打開以後會建立一個「mydatebase.db」的文件用於保存數據。若是文件名是「:memory:」,表示是一個內存數據庫(相似h2那種),數據不會持久化保存,當關閉數據庫時,內容將丟失。
mode(可選):數據庫的模式,共3種值:sqlite3.OPEN_READONLY(只讀),sqlite3.OPEN_READWRITE(可讀寫)和sqlite3.OPEN_CREATE(能夠建立)。 默認值爲OPEN_READWRITE |OPEN_CREATE。
callback(可選):則當數據庫成功打開或發生錯誤時,將調用此函數。 第一個參數是一個錯誤對象,當它爲空時,表示打開成功。
打開一個數據庫,如:
執行後會在項目的根目錄生成一個「mydatebase.db」文件,這就是sqlite保存數據的文件了。
關閉數據庫
該方法能夠關閉一個數據庫鏈接對象,參數:
callback(可選):關閉成功的回調。 第一個參數是一個錯誤對象,當它爲「null」時,表示關閉成功。
執行DDL和DML語句
該方法能夠執行DDL和DML語句,如建表、刪除表、刪除行數據、插入行數據等,參數:
sql:要運行的SQL字符串。sql的類型是DDL和DML,DQL不能使用這個命令。執行後返回值不包含任何結果,必須經過callback回調函數獲取執行結果。
param,...(可選):當SQL語句包含佔位符(?)時,這裏能夠傳對應的參數。 這裏有三種傳值方法,如:
關於佔位符的命名,sqlite3還支持更復雜的形式,這裏再也不擴展,有興趣瞭解的話請查看官方文檔。
callback(可選):若是執行成功,則第一個參數爲null,不然就是出錯。
若是執行成功,上下文this包含兩個屬性:lastID和changes。lastID表示在執行INSERT命令語句時,最後一條數據的id;changes表示UPADTE命令和DELETE命令時候,影響的數據行數。
執行多條語句
Database#exec與Database#run函數同樣,都是DDL和DML語句,可是Database#exec能夠執行多條語句,而且不支持佔位符參數。
查詢一條數據
sql:要運行的SQL字符串。sql的類型是DQL。這裏僅返回第一條查詢到的數據。
param,...(可選):同Database#run的param參數
callback(可選):一樣是返回null表明執行成功。回調的簽名是function(err,row)。若是查詢結果集爲空,則第二個參數爲undefined;不然第二個參數值是查詢到的第一個對象,他是個json對象,屬性名稱對應於結果集的列名稱,所以查詢的每一列都應該給出一個列表名。
查詢全部數據
sql:要運行的SQL字符串。sql的類型是DQL。和Database#get不一樣,Database#all會返回全部查詢到的語句。
param,...(可選):同Database#run的param參數
callback(可選):一樣是返回null表明執行成功。回調的簽名是function(err, rows) 。rows是一個數組,若是查詢結果集爲空數組。
注意,Database#all首先檢索全部結果行並將其存儲在內存中。 對於數據量可能很大的查詢命令時候,請使用Database#each函數或Database#prepare代替這個方法。
遍歷數據
與Database#run函數相同,都是查詢多條數據,可是具備如下區別:
回調的簽名是function(err,row)。若是結果集成功但爲空,則不會調用回調。對於每一個檢索到的行,該方法都會調用一次回調。執行順序與結果集中的行順序徹底對應。
調用全部行回調後,若是存在complete回調函數,將調用這個回調。第一個參數是一個錯誤對象,第二個參數是檢索行數。
預編譯SQL相關api
在java的jdbc中,有個PreparedStatement相關的api,能夠預編譯sql語句,執行的時候再連接具體參數。這樣的好處是能夠減小sql語句被編譯的次數。在sqlite3中,也存在實現這樣功能的api。
Database#prepare執行後,會返回一個命令對象,這個命令對象能夠反覆執行。下面看看這個命令對象(statement )的api:
以上api方法與Database的同名方法調用方式相同。不一樣點是這裏的Statement對象是能夠複用的,避免了重複編譯sql語句,所以項目中更推薦使用上述方法。
注意,這些方法的param參數都會對Statement對象綁定參數,在下一次執行的時候,若是沒有從新綁定參數,是會使用上一次參數的。
綁定參數
Database#prepare執行的時候,是能夠綁定參數的。不過使用此方法能夠全重置語句對象和行遊標,並刪除全部先前綁定的參數,實現從新綁定的功能。
重置語句的行遊標
重置語句的行遊標,並保留參數綁定。使用此功能可使用相同的綁定從新執行相同的查詢。
數據庫事務
事務是關係型數據庫中的一個重要部分,sqlite天然也是支持事務的,可是sqlite3並無提供特殊API去實現的事務相關的操做,只能靠SQL語句去控制事務。這裏舉一個事務相關的例子。
對SQLCipher的支持
SQLCipher是一個在SQLite基礎之上進行擴展的開源數據庫,他和SQLite不一樣就是提供了對數據的加密,可提供數據庫文件的透明256位AES加密。
sqlite3的官網特地說起他對SQLCipher的集成,若是要集成sqlcipher須要在編譯時候經過構建選項告訴sqlite3要集成的是SQLCipher:
不過筆者並沒嘗試對SQLCipher的集成,具體集成方法請自行查閱官網對這部分的詳細介紹。
基於promise對sqlite3API的封裝
sqlite3的API是node早期的API風格,對異步的書寫風格並不友好,很容易出現「金字塔回調」式的代碼。爲了讓對API的調用更加優雅,咱們每每會把回調封裝成Promise。事實上這個工做並不須要咱們本身作,sqlite3生態下已經有其餘庫能夠實現這樣的功能。sqlite就是一個這樣的庫。他基於sqlite3,隻手用Promise從新封裝了一下sqlite3的API,使其代碼風格更加優雅,也更容易使用。