nw.js连接mysql_nodejs集成sqlite使用示例_易个小小钡原子的博客-程序员宅基地

技术标签: nw.js连接mysql  

正在物色node上面的轻量级嵌入式数据库,作为嵌入式数据库的代表,sqlite无疑是个理想的选择方案。npm上集成sqlite的库主要有两个——sqlite3和realm。

realm是一个理想的选择方案,它最初是为移动app设计的,在node也可以运行的,但是不支持Windows系统。sqlite3是一个专为nodejs设计的,在nodejs上面生态更健壮,因此最终选择sqlite3。

sqlite3几乎支持所有版本的nodejs,同时也可以和nwjs集成。

安装

基于npm安装

npm install sqlite3

这样除了安装完sqlite3的npm包,最主要的是也装完了sqlite数据库,因为sqlite是嵌入式数据库,嵌入到客户端中。sqlite3使用node-pre-gyp为各个平台下载指定的预编译的二进制文件。如果无法下载到预编译的二进制文件,sqlite3将使用node-gyp和源代码来构建扩展。

这个过程出现两个的库——node-pre-gyp和node-gyp。他们究竟是什么呢?

node-gyp是一个跨平台的命令行工具,用于编译C++编写的nodejs扩展,首先gyp是为Chromium项目创建的项目生成工具,可以从平台无关的配置生成平台相关的Visual Studio、Xcode、Makefile的项目文件,node-gyp就是将其集成到nodejs中。因为linux的二进制分发快平台做的并不好,所有npm为了方便干脆就直接源码分发,用户装的时候再现场编译。不过对有些项目二进制分发就比源码分发简单多了,所以还有个node-pre-gyp来直接二进制扩展的分发。

两者区别在于node-gyp是发布扩展的源码,然后安装时候编译;node-pre-gyp是直接发布编译后的二级制形式的扩展。

和sqlite3一样的需要基于node-gyp安装的npm模块也有很多,比如node-sass等,都是发布源代码,然后编译安装。

基础api

sqlite3的api都是基于函数回调的,因为nodejs中没有像java的jdbc那种官方的数据库客户端接口,因此每个数据库的api都不一样,这里简单介绍几个sqlite3重要的api。

新建并打开数据库

new sqlite3.Database(filename, [mode], [callback])

该方法返回一个自动打开的数据库对象,参数:

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"

var database;

database = new sqlite3.Database("mydatebase.db", function(e){

if (err) throw err;

});

//也可以使用内存型,数据不会永久保存

database = new sqlite3.Database(":memory:", function(e){

if (err) throw err;

});

执行后会在项目的根目录生成一个“mydatebase.db”文件,这就是sqlite保存数据的文件了。

关闭数据库

Database#close([callback])

该方法可以关闭一个数据库连接对象,参数:

callback(可选):关闭成功的回调。 第一个参数是一个错误对象,当它为“null”时,表示关闭成功。

执行DDL和DML语句

Database#run(sql, [param, ...], [callback])

该方法可以执行DDL和DML语句,如建表、删除表、删除行数据、插入行数据等,参数:

sql:要运行的SQL字符串。sql的类型是DDL和DML,DQL不能使用这个命令。执行后返回值不包含任何结果,必须通过callback回调函数获取执行结果。

param,...(可选):当SQL语句包含占位符(?)时,这里可以传对应的参数。 这里有三种传值方法,如:

// 直接通过参数传值.

db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2);

// 将值封装为一个数组传值.

db.run("UPDATE tbl SET name = ? WHERE id = ?", [ "bar", 2 ]);

// 使用一个json传值.参数的前缀可以是“:name”,“@name”和“$name”。推荐用“$name”形式

db.run("UPDATE tbl SET name = $name WHERE id = $id", {

$id: 2,

$name: "bar"

});

关于占位符的命名,sqlite3还支持更复杂的形式,这里不再扩展,有兴趣了解的话请查看官方文档。

callback(可选):如果执行成功,则第一个参数为null,否则就是出错。

如果执行成功,上下文this包含两个属性:lastID和changes。lastID表示在执行INSERT命令语句时,最后一条数据的id;changes表示UPADTE命令和DELETE命令时候,影响的数据行数。

db.run("UPDATE foo SET id = 1 WHERE id <= 500", function(err) {

if (err) throw err;

//使用this.changes获取改变的行数

assert.equal(500, this.changes);

done();

});

执行多条语句

Database#exec(sql, [callback])

Database#exec与Database#run函数一样,都是DDL和DML语句,但是Database#exec可以执行多条语句,并且不支持占位符参数。

database.run("CREATE TABLE foo (id INT)", function(e){

if(e !== null){

throw e;

}

//循环生成sql语句,批次插入多条数据

var sql = "";

for(var i = 0 ; i < 500; i ++){

sql += 'INSERT INTO foo VALUES(' + i + ');'

}

database.exec(sql, done)

});

查询一条数据

Database#get(sql, [param, ...], [callback])

sql:要运行的SQL字符串。sql的类型是DQL。这里仅返回第一条查询到的数据。

param,...(可选):同Database#run的param参数

callback(可选):同样是返回null代表执行成功。回调的签名是function(err,row)。如果查询结果集为空,则第二个参数为undefined;否则第二个参数值是查询到的第一个对象,他是个json对象,属性名称对应于结果集的列名称,因此查询的每一列都应该给出一个列表名。

查询所有数据

Database#all(sql, [param, ...], [callback])

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#each(sql, [param, ...], [callback], [complete])

与Database#run函数相同,都是查询多条数据,但是具有以下区别:

回调的签名是function(err,row)。如果结果集成功但为空,则不会调用回调。对于每个检索到的行,该方法都会调用一次回调。执行顺序与结果集中的行顺序完全对应。

调用所有行回调后,如果存在complete回调函数,将调用这个回调。第一个参数是一个错误对象,第二个参数是检索行数。

语句执行顺序

sqlite3的API都是异步的,这就会出现可能有若干个命令同时进行的情况,因此sqlite3提供了两个函数来帮助控制语句的执行流程。默认是并行模式。

序列化执行

Database#serialize([callback])

如果提供回调,它将立即被调用,即此方法的回调不是异步回调。在该回调中调度的所有数据库语句将被序列化运行,即一个接一个地执行。 函数返回后,数据库将再次设置为其原始模式。

// 这里执行的命令是并行的

db.serialize(function() {

// 这里执行的命令是串行的

db.serialize(function() {

// 这里执行的命令是串行的

});

// 这里执行的命令是串行的

});

// 这里执行的命令是并行的

并行执行模式

Database#parallelize([callback])

如果提供回调,它将立即被调用,即此方法的回调不是异步回调。在该回调中调度的所有数据库语句将并行运行。函数返回后,数据库将再次设置为其原始模式。

db.serialize(function() {

// 这里执行的命令是串行的

db.parallelize(function() {

// 这里执行的命令是并行的

});

// 这里执行的命令是串行的

});

预编译SQL相关api

在java的jdbc中,有个PreparedStatement相关的api,可以预编译sql语句,执行的时候再链接具体参数。这样的好处是可以减少sql语句被编译的次数。在sqlite3中,也存在实现这样功能的api。

Database#prepare(sql, [param, ...], [callback])

Database#prepare执行后,会返回一个命令对象,这个命令对象可以反复执行。下面看看这个命令对象(statement )的api:

Statement#run([param, ...], [callback])

Statement#get([param, ...], [callback])

Statement#all([param, ...], [callback])

Statement#each([param, ...], [callback])

以上api方法与Database的同名方法调用方式相同。不同点是这里的Statement对象是可以复用的,避免了重复编译sql语句,因此项目中更推荐使用上述方法。

! 注意,这些方法的param参数都会对Statement对象绑定参数,在下一次执行的时候,如果没有重新绑定参数,是会使用上一次参数的。

绑定参数

Statement#bind([param, ...], [callback])

Database#prepare执行的时候,是可以绑定参数的。不过使用此方法可以全重置语句对象和行游标,并删除所有先前绑定的参数,实现重新绑定的功能。

重置语句的行游标

Statement#reset([callback])

重置语句的行游标,并保留参数绑定。使用此功能可以使用相同的绑定重新执行相同的查询。

数据库事务

事务是关系型数据库中的一个重要部分,sqlite自然也是支持事务的,但是sqlite3并没有提供特殊API去实现的事务相关的操作,只能靠SQL语句去控制事务。这里举一个事务相关的例子。

var db = new sqlite3.Database(db_path);

db.run("CREATE TABLE foo (id INT, txt TEXT)");

db.run("BEGIN TRANSACTION");

var stmt = db.prepare("INSERT INTO foo VALUES(?, ?)");

for (var i = 0; i < count; i++) {

stmt.run(i, randomString());

}

db.run("COMMIT TRANSACTION");

对SQLCipher的支持

SQLCipher是一个在SQLite基础之上进行扩展的开源数据库,他和SQLite不同就是提供了对数据的加密,可提供数据库文件的透明256位AES加密。

sqlite3的官网特意提及他对SQLCipher的集成,如果要集成sqlcipher需要在编译时候通过构建选项告诉sqlite3要集成的是SQLCipher:

npm install sqlite3 --build-from-source --sqlite_libname=sqlcipher --sqlite=/usr/

node -e 'require("sqlite3")'

不过笔者并没尝试对SQLCipher的集成,具体集成方法请自行查阅官网对这部分的详细介绍。

基于promise对sqlite3API的封装

sqlite3的API是node早期的API风格,对异步的书写风格并不友好,很容易出现“金字塔回调”式的代码。为了让对API的调用更加优雅,我们往往会把回调封装成Promise。事实上这个工作并不需要我们自己做,sqlite3生态下已经有其他库可以实现这样的功能。sqlite就是一个这样的库。他基于sqlite3,只手用Promise重新封装了一下sqlite3的API,使其代码风格更加优雅,也更容易使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42578963/article/details/113469294

智能推荐

许多同学应该都还记得联考前夕的焦虑-程序员宅基地

许多同学应该都还记得联考前夕的焦虑:差一分可能要掉好几个志愿,甚至于一生的命运从此改观!到了大四 ,这种焦虑可能更强烈而复杂:到底要先当兵,就业,还是先考研究所?  我就经常碰到学生充满焦虑的问我这些问题。可是,这些焦虑实在是莫须有的!生命是一种长期而持续的 累积过程,绝不会因为单一的事件而毁了一个人的一生,也不会因为单一的事件而救了一个人的一生。属于我 们该得的,迟早会得到;属于我们

uv422转换为yuv420_YUV422格式信号格式(以备学习之用)_Fay-颜的博客-程序员宅基地

YUV信号有很多种,一般YUV420和YUV422用的比较多,YUV422格式,又分为很多小类,按照U、V的排列可以有YUYV,YVYU,UYVY,VYUY四种,其中,YUYVY一般又称作yuv2格式。而这四种YUV422格式,每种又可以分为2小类,按Y和UV的排列可以有打包格式和平面格式。例如,一个640×480×2的YUV文件,打包格式就是YUYVYUYV这样一直排列下去,平面格式就是先640..._uvy zhuan yuv

李昂 软件工程第一次作业-程序员宅基地

第1次个人作业2.分析软件第一部分结缘计算机1.计算机是你喜欢的领域吗?是你擅长的领域吗?这两个问题,不得不说我的答案都是否。我很难喜欢计算机编程,更遑论软件硬件原理等等,感觉有些晦涩了,无法让我很有兴趣。如果不是现实的要求,不会计算机技术的工科生可能寸步难行,我可能不会主动接触计算机编程等等。博客I中提到从中学就开始喜欢计算机,我表示我就默默仰望一下吧。当然,没有兴趣,之前也没...

css伪类选择器之first-child,last-child,nth-child()_代码li:last-child a-程序员宅基地

今天没上班,脑袋不太清晰,就简单给小白们讲一个很实用的css伪类选择器,这个在你们写导航或者其他列表类的css时特别实用,而且利于后期维护。这个选择器就是 元素:fist-child / last-child / nth-child(子节点序号)例如此时我们需要写一个一级导航:&lt;!DOCTYPE html&gt;&lt;html&gt; &lt;head&gt;..._代码li:last-child a

串级PID介绍_串级pid好处-程序员宅基地

串级PID的模块图如下:前提条件:中间变量可观测中间变量可控中间变量可以反应扰动的干扰中间变量的反应比终末变量的反应快特点:(1) 由于内环回路的存在,改变了原来的对象特性,使内环回路对象的等效时间常数变小,所以使系统的过渡时间缩短了,控制作用更加及时;(2) 改善了对象特征,起到超前控制的作用,有效抑制内环回路干扰,这种超前控制作用最适合干扰落在内环回路内的情况,若干扰落在外环..._串级pid好处

php 防止爬虫,服务器反爬虫攻略:Apache/Nginx/PHP禁止某些User Agent抓取网站-程序员宅基地

我们都知道网络上的爬虫非常多,有对网站收录有益的,比如百度蜘蛛(Baiduspider),也有不但不遵守robots规则对服务器造成压力,还不能为网站带来流量的无用爬虫,最近发现nginx日志中出现了好多垃圾爬虫的抓取记录,于是整理收集了网络上各种禁止垃圾蜘蛛爬站的方法,在给自己网做设置的同时,也给各位站长提供参考。一、Apache①、通过修改 .htaccess文件修改网站目录下的.htacce..._php反爬虫

随便推点

同步IO与异步IO_synchronous io oper-程序员宅基地

IO模型介绍同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出的答案都可能不同,比如wiki,就认为asynchronous IO和non-blocking IO是一个东西。这其实是因为不同的人的知识背景不同,并且在讨论这个问题的时候上下文(con..._synchronous io oper

Jenkins与git实现联动_jenkins repository url 可以写 git clone吗-程序员宅基地

一、问题背景 在开发过程中,有时候在git 主干上合并代码后,将代码部署到测试环境或者开发环境中,如果每次主干更改都需要重新部署,相对恶言就比较麻烦。本节主要介绍如何通过Jenkins实现与git的联动,即Jenkins监控代码托管仓库git的状态,如果git有变动,自动触发Jenkins执行构建操作,如代码部署、自动化测试等。 二、Jenkins job配置 (1)关于Jenki..._jenkins repository url 可以写 git clone吗

MATLAB中的size返回值_matlabsize返回值-程序员宅基地

[X,Y]=size(A)返回值的含义是X行,Y列_matlabsize返回值

Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别-程序员宅基地

spring事务配置的五种方式前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。 总结如下: Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和

[MySQL] myisam比innodb查询过程效率探究-程序员宅基地

当查询非主键的字段时 , MyISAM查询性能更好,从索引文件数据文件的设计来看 , myisam每一个索引字段都有上面的索引树:MyISAM直接找到物理地址后就可以直接定位到数据记录,但是InnoDB查询到叶子节点后,还需要再查询一次主键索引树,才可以定位到具体数据。等于MyISAM一步就查到了数据,但是InnoDB要两步,那当然MyISAM查询性能更高如果是查询的主键的字段时..._msyql myisam与innodb 主键和非主键查询效率那个更快