对于官方的API文档只能做到一个很粗略的了解到Storge的一些东西,而对于一些详细的东西,比如说对于SQLite的操作到底那些是phoneGap已经提供了的,还是要解读一下源文件啊。通过对源文件的粗略解读,总结了以下内容。由于本人水平有限,有些地方还是没明白,有待接下来继续学习。
一、openDatabase
通过官方的文档我们可以了解到它有四个可选的参数。刚开始对于name和display_name之间的关系搞不明白。后台查看数据库文件才知道,当我们调用openDatabase的时候,例如:window.openDatabase("Database", "1.0", "PhoneGap Training", 200000) 。它会在项目包下的app_database文件夹下创建一个Databases.db的数据库文件,然后在这个数据库文件中创建一个表:Databases。表中的数据就是我们填写的参数信息,并且指出了我么真正创建的数据库文件夹路径和文件路径,默认第一次创建是在file__0/ 0000000000000001.db.这个才是我们真正创建的数据库文件。你调用数据库对象进行数据库操作都是在这个数据库下进行的。
当我们指定的数据库不存在时会帮我们新建一个数据库,当存在了只会返回一个已有的数据库对象。
二、SQLTransaction
当我们得到了数据库对象之后,就可以进行一些操作。文档中给出了两个方法:
- transaction:运行一个数据库事务。
- changeVersion:该方法允许脚本执行以下原子操作:校验数据库的版本号并更新版本号以完成架构更新。
在这里我主要讲一下transaction。Transaction主要是通过回调函数的方法来运行数据库事务。文档中给的一个例子中有:db.transaction(populateDB, errorCB, successCB);
其中populateDB可以通过多次调用executeSql来建立一个数据库事务处理,从而对数据库进行操作,但是有一个要注意的是:当你需要参数的时候,这里给不进去。因为我们操作数据库的时候不可能每次都是我们写死了数据写进去的,需要用户自己输入的数据。我测试了一下,如果使用populateDB直接回调的话是不行的。但是有一个办法可以解决。errorCB和successCB就不用多讲了,当事务处理错误或者成功的时候会回调这两个函数。
刚才讲到一个,当我们需要将用户输入的数据去处理数据库的时候,不可以用上面的方法。而是需要这样:
db.transaction(
function (transaction) {
transaction.executeSql('INSERT INTO DEMO (id, data) values(?,?)',[id,data]);
}, errorCB, successCB
);
这样就可以将传参数进来,写进数据库里面了。
三、SQLResultSet
接下来讲一下关于结果集的。但我们使用select执行查询后需要返回结果集,那么我们就需要用到SQLResultSet。如何得到结果集呢?当我们调用数据库事务对象transaction执行executeSql查找的时候,这时候就需要添加一个回调函数作为参数了。参考文档中的例子:tx.executeSql('SELECT * FROM DEMO', [], querySuccess, errorCB);
第一个参数为要执行的数据库语句。与普通操纵数据库语句没太大区别。
第二个参数为一个数组对象,存放sql语句中需要的参数的数组,就是sql语句里面出现的?所需要的参数。
第三个参数为执行成功后,调用的方法,在这个函数中可以获取到结果集results.
第四个参数为执行错误时候调用的方法。
接下来我们看一下querySuccess这个回调方法。
function querySuccess(tx, results) {
// 因为没有插入记录,所以返回值为空
console.log("Insert ID = " + results.insertId);
// 因为这是一条查询语句所以返回值为0
console.log("Rows Affected = " + results.rowAffected);
// 返回查询到的记录行数量
console.log("Insert ID = " + results.rows.length);
}
Results这个东西就比较强大了,参考官方文档:
- insertId:SQLResultSet对象通过SQL语句插入到数据库的行记录的行ID。[译注:如果插入多行的时候,返回最后一个行的ID]
- rowAffected:被SQL语句改变的记录行数,如果语句没有影响任何行则设置为0。
- rows:是一个SQLResultSetRowList对象,表示返回的多条记录。如果没有返回任何记录,则此对象为空。
这个对象就是上面的rows了。
SQLResultSet对象的一个属性,包含SQL查询所返回的所有行数据。
属性:
- length: SQL查询所返回的记录行数。
方法:
- item:根据指定索引返回一个行记录的JavaScript对象。
使用方法:
function querySuccess(tx, results) {
var len = results.rows.length;
console.log("DEMO table: " + len + " rows found.");
for (var i=0; i<len; i++){
console.log("Row = " + i + " ID = " +results.rows.item(i).id + " Data = " + results.rows.item(i).data);
}
}
总结:说了那么多,但是我还是有疑问,疑问是来自于对storage.java解读时产生了。
if (isDDL(query))
{
myDb.execSQL(query);
sendJavascript((new StringBuilder()).append("cordova.require('cordova/plugin/android/storage').completeQuery('").append(tx_id).append("', '');").toString());
} else
{
Cursor myCursor = myDb.rawQuery(query, params);
processResults(myCursor, tx_id);
myCursor.close();
}
privateboolean isDDL(String query)
{
String cmd = query.toLowerCase();
return cmd.startsWith("drop") || cmd.startsWith("create") || cmd.startsWith("alter") || cmd.startsWith("truncate");
疑问原因:
这是一个判断,但sql语句是DDL语句的时候会直接不带参数执行query语句,也就是当我想执行插入数据的时候,比如说insert,这样就会跳到下面myDb.rawQuery(query, params);可是我查了文档,不是说rawQuery不可以执行insert语句的吗?这就是我的疑问。。。