2012年3月5日月曜日

SQLite について

android でのSQLite 実装について書きます。

SQLite というのはデータベースであり、イメージとしては、こんな感じです。



① まず、メインとは別に、SQLiteのHelperクラスを作ります。

エクリプスで新しいクラスを選び、スーパークラスに SQLiteOpenHelper を指定して、クラス名は適当につけてクラス作成。
すると、onCreate と onUpgrade(必須のメソッド)が自動的に作成されます。

(自分の環境だと)クラス名のところにエラー出るのでポインタ合わせると、コンストラクタを作って的なメッセージ。そのままクリック。すると、自動的にコンストラクタが作成されます。

コンストラクタとonUpgradeメソッドは、そのままで大丈夫ですが、onCreate に処理を書く必要があります。

■ onCreate の処理
db.execSQL()メソッドの引数にSQL文を書きます。

以下の設定とすると、
・ テーブル名:hoge
・ カラム名A:fuga(テキスト情報)
・ カラム名B:piyo(数値情報)

文字列で、

"create table if not exists "+
"hoge"+
"(_id INTEGER primary key autoincrement,"+
"fuga"+" TEXT,"+
"piyo"+" INTEGER)"

と書きます。

最初は定型文。
三行目は、お約束。(これの実装が前提に作られているものが多いらしい)

これで、ヘルパークラスの作成は終わりです。


② 次にメイン側での処理。

上で作成したヘルパークラスのインスタンスを作成します。
その際の引数について。(これがヘルパークラスのコンストラクタに引き渡される)

・第1引数:Context
・第2引数:データベース名
・第3引数:CursorFactory(不明)
・第4引数:データベースのVersion

第1引数のContext には、getApplicationContext() を指定します。
第2引数は、データベース名です。任意の文字.db
第3引数は、よくわかりません。null でいいと思います。
第4引数は、Versionということですが、とりあえず1でいいです。

これに、getWritableDatabase() メソッドを使い、
SQLiteDatabase クラスの変数に代入して、準備完了です。


■ データベースに書き込むには?
execSQL()メソッドにSQL文を書く手もありますが、これを使わない方法もあります。
ContentValues クラスを使います。(データベース未経験なら、こちらのほうが分かりやすいかも)

ContentValues クラスの変数に、put メソッドを使い、カラム名とデータを指定します。
必要なデータをまとめておくわけです。

・ 追加したい場合は、
SQLiteDatabase クラスの変数に、insert() メソッドを使い、
第1引数:テーブル名
第2引数:(不明)null
第3引数:上で作成したContentValues クラスの変数を指定

・ 更新したい場合は、
update()メソッドを使います。
第1引数:テーブル名
第2引数:上で作成したContentValues クラスの変数を指定
第3引数:更新する条件にするカラム名
第4引数:第3引数に指定したカラム名にあるデータ

ContentValues の変数は、使ったら clear() メソッドで掃除しましょう。

※応用
update() メソッドは、更新したレコード数を返します。
よって、0が返ってきたら、更新するものがなかったと判断。
最初に update() し、if文で0だったら insert() するという書き方ができます。


■ データベースからデータを任意の形で取得するには?
Cursol クラスのインスタンスを、SQLiteDatabase のquery メソッドで取得します。

query の引数は以下。
第1引数:テーブル名
第2引数:取得するカラム名
第3引数:検索条件
第4引数:検索条件の値
第5引数:group by 句
第6引数:Having 句
第7引数:order by 句

必須なのは第1引数のみです。(使わないところはnull
これで指定したテーブル名のデータが取れます。

条件、例えば、カラムBの値で、降順で取得したい場合は、
第7引数(order by)に、"カラムB DESC"と指定します。

ここで、最初の画象の「1行目 ⇒」となっているイメージ、つまりカーソルという概念でデータを一行ずつ取得します。

moveToFirst() で頭に移動。
Cursol の getColumnIndex() の引数にカラム名を指定してデータ取り。
moveToNext() で次の行へ移動。

Cursol は、使い終わったら、Close します。


おしまいに、onDestroy() で
SQLiteDatabase と SQLiteOpenHelper のインスタンスにclose() メソッドをかけましょう。

追記)クローズについて
以下の記事
http://d.hatena.ne.jp/ukiki999/20100524/p1
では、明示的にクローズする必要ないとのこと。

追記2)
ためしにClose処理を外してみたところ、
android.database.sqlite.SQLiteException: database is locked
エラーが発生。
onCreate でオープンにしてるところで。
ただし頻度は非常に低いようです。
また本当にこれが原因だったのかどうか?
どうもSQLite はよく分からないことが多くて困ります。。

0 件のコメント: