11/26/2012

Android DatabaseでのSQLiteStatementについて

AndroidのDatabaseを使う際に、SQLiteDatabase.compileStatementメソッドでSQLiteStatementを生成する方法がある。これは、実装上Insert,Update,Replace,Deleteのためのものではなく、あくまでそれ以外の呼び出し、Create/Drop Table, View , Indexを呼び出す際に利用するものとJavaDocに記述されている。

SQLiteStatementのオブジェクトはSynchronaizedなので、他のスレッドと共有でつかうことはできない。また内部のBind処理に関して、利用が終了した時点でClearBindArgsを呼ばないとクリアされないので、その動作が関係しているのではないかと推察する。

またSQLiteStatementを利用しなくても、execSQL(String)と等価であるとあるので、CreateTableでは利用しないし、DropTableでもSQLiteStatementはあまり利用しないとおもわれる。Bindする要素がなく、そのSQLを隠蔽したい場合にのみ使うとかんがえられる。そしてViewの場合に利用することが多くなりそうである。ViewのSQLを作成しておいてBindを行い、利用する局面はありうる。

追記
JavaDocには、COUNT(*)などの場合の呼び出しに使う場合が記述してある。

追記
SQLiteStatementのクラスJavaDocコメントを以下に引用する。

A pre-compiled statement against a SQLiteDatabase that can be reused. The statement cannot return multiple rows, but 1x1 result sets are allowed. Don't use SQLiteStatement constructor directly, please use SQLiteDatabase.compileStatement(String) 
SQLiteStatement is NOT internally synchronized so code using a SQLiteStatement from multiple threads should perform its own synchronization when using the SQLiteStatement.
基本的にはViewとしても使えないと考える。MAX、MINやCOUNTなどの特別なProcedureでの利用が主なようだ。

AndroidでのDatabase処理でinsertOrUpdate

Android:Is there a better way to insert and/or update a database entry?

AndroidのSQLiteのSQLiteDatabaseの動作は、insertとupdateが明確に分離している。
これ自体は、必ず新しく追加したい、必ず更新したいという動作をするときに必要になる。しかしながら、項目があれば更新なければ追加という動作を行いたい場合がある。これに関しては上記の質問の回答である。REPLACEを使えばよい。

SQLiteDatabase.replace

もともとSQLiteにはReplaceが特別な動作として定義されている。他のテーブルの場合には、INSERT IF CONFLICT や INSERT OR UPDATEがあったりしたと思った。

AndroidでのLogCat用のTAGについて

AndroidでLogをLogCatに出力する際に、tag引数に、AndroidのSourceCodeでは大抵決まった書き方をしている。

 public class T {
     private static final String TAG = T.class.getSimpleName();
 }
 Tは任意のクラス名をつける。

このTAGを使えば、クラスに固有のTAGをつけることが可能になる。 EclipceでAndroidの開発を行なっているならばClassGeneratorに記述しておくこともいいのかもしれない。

Android Databaseについての覚書

Androidのandroid.databaseサブパッケージではSQLite向きのクラスは提供されていない。さらにそのサブパッケージである、android.database.sqliteに実装がある。


Classes

SQLiteClosableAn object created from a SQLiteDatabase that can be closed. 
SQLiteCursorA Cursor implementation that exposes results from a query on a SQLiteDatabase
SQLiteDatabaseExposes methods to manage a SQLite database. 
SQLiteOpenHelperA helper class to manage database creation and version management. 
SQLiteProgramA base class for compiled SQLite programs. 
SQLiteQueryRepresents a query that reads the resulting rows into a SQLiteQuery
SQLiteQueryBuilderThis is a convience class that helps build SQL queries to be sent to SQLiteDatabase objects. 
SQLiteStatementRepresents a statement that can be executed against a database. 

上記の表はandroid.database.sqliteのパッケージに登録されているClassである。これらのクラスでDatabaseを取り扱うときに利用するのは、SQLiteOpenHelperである。このクラスをサブクラス化して利用する。単純な実装としてはonCreate、onUpdateを利用することが必要とされているされてる。

これに拡張的なメソッド、例えばdeleteに対して、Androidでは_idのフィールドを必ずもつことから


  • deleteById(String tableName, long id)
のような実装を追加してやることで削除のためのSQLを書くことが減るだろう。

また、利用する際の注意点としてはinsertメソッドの戻り値は、_idもしくは-1が戻ること。これに対して、delete,updateなどのメソッドでは「変更された列数」もしくは-1が戻る。この違いは注意が必要である。

追記
Androidアプリで使用するSQLiteのテーブル作成時の注意点
こちらのサイトで_idが必要なこととその後のInsertでの利用について説明がされています。