23.14.本地SQL数据库

23.14.1.问题
我想让应用程序在本地保存和接收数据。
23.14.2.解决办法
在用户硬盘上创建数据库文件,执行SQL语句。
23.14.3.讨论
Adobe AIR 运行时引入了SQL数据库引擎,使我们可以为创建本地数据库存储信息。一个数据库被保存为一个文件,且没有限定存放于特定的目录下,这样可允许任何应用程序都可访问数据库中的数据。AIR的SQL引擎可创建关系型数据库,用标准SQL语句存储和接受复杂数据。

SQL 数据库API 包含几个类,提供创建和打开数据库,生成语句,监听操作事件,检索有关数据库的架构信息。使用flash.filesystem.File类用合法的扩展名创建数据库文件。使用Flash.dataSQLConnection类的open和openAsync方法建立一个数据库连接。如果你没有传递File引用给open和openAsync方法,则会在内存中创建一个数据库并允许执行SQL语句。SQL语句可被同步和异步执行。在执行SQL语句前可监听成功和失败相关事件,只不过异步执行操作是在主程序线程之外,这样在SQL执行时可以运行其他代码。

下面的例子演示在数据库存在时打开数据库,反之创建新的数据库文件:
+展开
-ActionScript
var db:File = File.applicationStorageDirectory.resolvePath("Authors.db");
var sqlConn:SQLConnection = new SQLConnection();
sqlConn.addEventListener( SQLEvent.OPEN, openHandler );
sqlConn.addEventListener( SQLErrorEvent.ERROR, errorHandler );
sqlConn.openAsync( db );
private function openHandler( evt:SQLEvent ):void {
trace( "Database created.");
}
private function errorHandler( evt:SQLErrorEvent ):void {
trace( "Error"+ evt.error.message + "::"+evt.error.details );
}

如果之前没有创建过Authors.db,则SQLConnection实例的openAsync方法会在应用程序存储目录创建这个数据库文件。如果操作成功,一个SQLEvent对象发出并调用openHandler 方法。

如果操作中出现错误,一个SQLErrorEvent被发出。SQLErrorEvent对象的error属性是一个SQLError对象继承自flash.errors.Error类。

要执行SQL语句,先赋值申明的SQL字符串值传递给SQLStatement的text属性并调用execute方法。下面的例子使用SQL语言的CREATE TABLE语句在数据库里创建一个新表:
+展开
-ActionScript
var db:File =File.applicationStorageDirectory.resolvePath( "Authors.db");
var sqlConn:SQLConnection = new SQLConnection();
sqlConn.addEventListener( SQLEvent.OPEN, openHandler );
sqlConn.addEventListener( SQLErrorEvent.ERROR, errorHandler );
sqlConn.openAsync( db );
private function openHandler( evt:SQLEvent ):void {
var sql:String = "CREATE TABLE IF NOT EXISTS authors ("+"authorId INTEGER PRIMARY KEY,"
+"firstName TEXT NOT NULL,"
+"lastName TEXT NOT NULL"+");";
var statement:SQLStatement = new SQLStatement();
statement.sqlConnection = sqlConn;
statement.text = sql;
statement.addEventListener( SQLEvent.RESULT, resultHandler );
statement.addEventListener(SQLErrorEvent.ERROR,errorHandler );
statement.execute();
}
private function resultHandler( evt:SQLEvent ):void {
trace ( "Table created." );
}
private function errorHandler( evt:SQLErrorEvent ):void {
trace ( "Error"+ evt.error.message +"::"+ evt.error.details );
}

当数据库连接被打开时,SQL语句被执行,创建了一个新的authors表,列名分别为authorId,firstName, 和lastName。SQLStatement对象通过其sqlConnection属性获得SQLConnection实例,在执行之前要注册相应的事件监听器。因为这里使用的是异步的openAsync方法,这样在执行异步方法时,其他操作也会继续被执行,不会被阻塞。

使用SQL声明性语言执行查询,除了CREATE TABLE 命令外,还有INSERT, SELECT,UPDATE, 和DELETE查询语句。下面的代码执行INSERT语句添加数据:
+展开
-ActionScript
private var insertQuery:SQLStatement = new SQLStatement();
private function addAuthor( fName:String, lName:String ):void {
var sql:String = "INSERT INTO authors VALUES ("+"null,"+"'"+ fName + "',"+"'"+ lName + "'"+");";
insertQuery.sqlConnection = sqlConn;
insertQuery.text = sql;
insertQuery.addEventListener( SQLEvent.RESULT, insertHandler );
insertQuery.addEventListener( SQLErrorEvent.ERROR,errorHandler );
insertQuery.execute();
}
private function insertHandler( evt:SQLEvent ):void {
var result:SQLResult = insertQuery.getResult();
trace( "Row ID:"+ result.lastInsertRowID + "/"+"#Rows Affected:"+ result.rowsAffected );
}

使用INSERT INTO SQL语句Author数据被添加到authors数据库表中。如果操作成功,insertHandler方法被调用,SQLStatement实例的getResult方法收到SQLResult对象。

要简化和增强执行查询语句的性能,SQLStatement类提供了一个parameters属性和itemClass属性。像这里的情况,一个同样的Insert语句可能使用不同的插入内容调用很多次,这时候就可以使用SQLStatemnt的parameters属性,parameters属性是一个关联数组,使用命名的和未命名的参数存储键---值对。

下面的例子使用命名参数:
+展开
-ActionScript
var insertSql:String = "INSERT INTO authors VALUES ("+"null,:firstName,:lastName);";
insertQuery.sqlConnection = sqlConn;
insertQuery.text = insertSql;
insertQuery.parameters[":firstName"] = fName;
insertQuery.parameters[":lastName"] = lName;

当语句被执行前,这些值被替换,你可以在属性名前使用:或@符号,也可以是数字索引作为属性名,SQL语句里用?取代:
+展开
-ActionScript
var insertSql:String = "INSERT INTO authors VALUES("+"null,?,?);";
insertQuery.sqlConnection = sqlConn;
insertQuery.text = insertSql;
insertQuery.parameters[1] = lName;

当执行语句时每个索引下的值会替换掉SQL语句中的?符号。这样做的好处是不仅提高了执行效率,而且提高了抵御如SQL注入等恶意攻击。

如果你的程序有个数据对象关联到本地数据库的表数据,那么通过SQLStatement的itemClass属性可以很方便的映射SELECT查询获得的行数据结果。下面的例子代码使用itemClass属性映射com.oreilly.flexcookbook.Author类返回的author数据:
+展开
-ActionScript
import com.oreilly.flexcookbook.Author;
private var selectQuery:SQLStatement = new SQLStatement();
private function getAuthors():void {
var sql:String = "SELECT authorId,firstName,lastName FROM authors";
selectQuery.sqlConnection = sqlConn;
selectQuery.text = sql;
selectQuery.itemClass = Author;
selectQuery.addEventListener( SQLEvent.RESULT, selectHandler );
selectQuery.addEventListener( SQLErrorEvent.ERROR,errorHandler );
selectQuery.execute();
}
private function selectHandler( evt:SQLEvent ):void {
var authors:Array = selectQuery.getResult().data;
forvar i:int = 0; i < authors.length; i++ ){
var author:Author = authors[i] as Author;
trace( author.firstName + " "+ author.lastName );
}
}

当查询成功时,selectHandler方法被调用,SQLStatement实例的getResult方法得到SQLResult对象,SQLResult对象的data属性是一个数据库行记录数组,数组中的每个元素被映射为Author对象,因为Author类已提供给itemClass属性。

关于SQL语言已经有很多书可以查阅,本节重点介绍在本地数据库执行查询语句。

加支付宝好友偷能量挖...


评论(0)网络
阅读(112)喜欢(0)flash/flex/fcs/AIR