homeへのリンクです。

SQLiteを使ったAIRのオフライン運用術 その2

2007年11月24日

デモ1の画面は以下のような具合だが、

sqlitedemo1.png

"プログラムからLoad"ボタンで呼び出される処理以下のような感じになっている。

private function programLoad():void{
   var count:int = 10;
   for(var i:int = 0;i < count;i++){
      var tmp:Object = new Object();			
      tmp["col1"] = i;
      tmp["col2"] = i + "行目";
      tmp["col3"] = i % 2 == 0 ? true : false;
      testdata.addItem(tmp);
   }
}

3カラムの情報を含むtmpオブジェクトを、testdataに10回追加する処理。

testdataというのは、mxmlの定義部分で以下のように定義されているオブジェクトのこと。

<mx:ArrayCollection id="testdata"/>

これが以下のような具合に、データグリッドにバインドされているので、メソッドの処理でtestdataにtmpを追加するたびに、その値がデータグリッドに表示されることになっている。

<mx:DataGrid id="dg" x="10" y="10" dataProvider="{testdata}">

データグリッドのカラムは以下のように定義する。

<mx:columns>
   <mx:DataGridColumn headerText="カラム 1" dataField="col1"/>

この際指定しているdataField名が、tmpに含まれているオブジェクト名と一致しているので、対応するカラムにデータが入って行くことになっている。

"プログラムからload"がクリックされると以下のような表示になる。

sqlitedemo1_2.png

デモ1のデモンストレーションとしては、このデータを"SQLiteにSave"ボタンをクリックして、ローカルのSQLiteに保存し、その後、データグリッドをクリアし、今度は"SQLiteからLoad"ボタンをクリックして、データを復帰させ、ローカルのデータベースとして機能していることを確認する。

データグリッドをクリアする変わりに、アプリケーションを終了させた後、再度アプリケーションを起動して、"SQLiteからLoad"ボタンをクリックしても、データはローカルのデータベースに保存されるので、同じようになる。

SQLiteにデータを保存する処理は以下のようになっている。

private function sqliteSave():void{
   var tmpdb:SQLConnection = new SQLConnection(true);※1
   var file:File = new File(File.separator + file_name);
   try{
      tmpdb.open(file);
      tmpdb.begin();※2
      var deletedata:SQLStatement = new SQLStatement();
      deletedata.sqlConnection = tmpdb;
      deletedata.text = "delete from TEST_TABLE1";※3
      deletedata.execute();
      var count:int = testdata.length;
      for(var i:int = 0;i < count;i++){
         var save:SQLStatement = new SQLStatement();
         var obj:Object = testdata[i];
         save.sqlConnection = tmpdb;
         save.text = "insert into TEST_TABLE1(col1,col2,col3) values (:data1,:data2,:data3)";※4
         save.parameters[":data1"] = obj["col1"];
         save.parameters[":data2"] = obj["col2"];
         save.parameters[":data3"] = obj["col3"];
         save.execute();
      }
      tmpdb.commit();※5
   }catch(e:SQLError){
      tmpdb.rollback();※6
   }finally{
      if(tmpdb.connected == true){
         tmpdb.close();
      }
    }
 }

※1のところで、トランザクション処理を設定するために、再度SQLConnectionインスタンスを生成している。
ここでコンストラクタにtrueの引数を渡すことで、エラーイベントをtray-catch-finallyステートメントで拾える形式で発行してくるれようになる。
トランザクション処理として、複数の処理をまとめるので、処理結果を受けるハンドラは、実行単位ではなくて、ブロック単位で定義できる必要がある。

※2でSQLConnectionのbeginメソッドを実行している。
beginメソッドの以下から、※5のcommitメソッド、または、※6のrollbackメソッドまでの間に実行される処理が、トランザクションのグループとされる。

トランザクションとして実行される処理は、
※3のテーブルのデリート
※4のデータのインサート処理
インサートの方法としては、SQLでカラムとパラメータを結びつけた後、パラメータにデータを割り当てている。

トランザクション単位で、処理が問題なく実行されたときは、SQLConnectionのcommitメソッドを実行して、データベースの更新処理を確定し、なんらかのエラーが発生した場合は、rollbackメソッドを実行して、トランザクション単位で処理を無効にする。

SQLiteからデータをロードする処理は以下のようになっている。

まずデータを呼び出す。

private function sqliteLoad():void{
   var load:SQLStatement = new SQLStatement();
				
   load.sqlConnection = db;
   load.text = "select * from TEST_TABLE1";
   load.execute();
   load.addEventListener(SQLEvent.RESULT,loadHandler,false,0,true);※1
}

SQLの実行が成功すると、※1で定義したリスナーメソッドが、SQLEventを引数として呼ばれる。

private function loadHandler(event:SQLEvent):void{
   var stmt:SQLStatement = event.currentTarget as SQLStatement;※1
				
   if(stmt != null){※2
      var res:SQLResult = stmt.getResult();※3
					
      testdata = new ArrayCollection(res.data);※4
   }
}

SQLEventはresultデータにアクセスするメソッドやプロパティを持っていないので、イベントターゲットのSQLStatementインスタンスからresultデータにアクセスする。

AS3では、イベントのターゲットはtargetとcurrentTargetの2種類になっている。
adobeのリファレンスによると、例えばボタンコンポーネントがクリックされて生成されたイベントの場合、targetはコンポーネントのDOMノードの一番末端で、実際にカーソルと接するテキストフィールドで、currentTargetの方は、コンポーネントのDOMの大元のボタンコンポーネント自身になるというような説明があるが、Displayオブジェクトではない場合はどちらも同じ。

asはキャストオペレータで、currentTargetで参照されるObjectをSQLStatementにキャストしています。

※2。AS3.0からランタイムエラーが出るようになっているので、null参照は厳禁なのでnullのチェックをします。

※3。SQLStatementのgetResultメソッドを使ってSQLResultを抽出します。

※4。SQLResultのdataプロパティに、SQLの結果のクエリデータが配列で入っているので、それをArreyCollectionにキャストして、データグリッドにバインドされているtestdataに格納します。

データグリッドの消去は、データグリッドにdataProviderとしてバインドされているtestdata ArrayCollectionのメソッドを使って、以下のように消去します。

private function gridClear():void{
   testdata.removeAll();
}

SQLiteのデータベースのクリアは、SQLStatementを実行して、以下のように消去しています。

private function sqliteDelete():void{
   var deletedata:SQLStatement = new SQLStatement();
			
   deletedata.sqlConnection = db;
   deletedata.text = "delete from TEST_TABLE1";
   deletedata.execute();
}