Android -データベース-
SQLite
Androidには、SQLiteというオープンソースのデータベースが標準でサポートされています。
SQLiteは、クライアントサーバ形式ではなく端末の中で処理が完結します。
また、取り扱いがシンプルで、サーバのホスト名やポート番号、ログインID、パスワードの指定も不要です。
保存先は、「data/data/パッケージ名/databases/ファイル名」となります。
プリファレンスとファイルと同様にアプリケーションごとにデータベースに保存するデータを管理し、 他のアプリケーションから直接操作できない仕組みになっている為、他のアプリケーションから操作する必要が ある場合は、コンテンツプロバイダを利用します。
SQLiteの主な命令
命令 | 説明 |
---|---|
create | テーブルの生成 |
drop | テーブルの削除 |
query | レコードの検索及び、データの抽出 |
update | レコードの更新 |
insert | レコードの挿入 |
delete | レコードの削除 |
詳しい仕様:SQLite公式サイト
ヘルパークラス
AndroidアプリケーションからデータベースのSQLiteを操作するためには、SQLiteOpenHelperクラスを継承したヘルパークラスを利用します。
このクラスは、データベースの生成及びアップグレードを管理します。
コンストラクタ
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
- context : コンテキスト
- name : データベース名
- factory : ファクトリー、通常はnullで問題ないようです。
- version : バージョン番号
実装するメソッド
- onCreateメソッド
データベース生成時に呼ばれます。 - onUpgradeメソッド
データベースアップグレード時に呼ばれます
データオブジェクトの取得
データベースの処理を扱うには、初めに作成したヘルパークラスをインスタンス化し、 引数にアクティビティのインスタンスを引き渡して、DBHelperオブジェクトを生成します。
次にSQLiteDatabaseオブジェクトをヘルパークラスの2つのメソッドを利用して取得します。
- getWritableDatabase()
読み書き用 - getReadableDatabase()
書き込み用
テーブルの作成
SQLiteDatabaseのexecSQLメソッドでSQL文を実行します。
execSQLメソッドは、CREATE文、DROP文、INSERT文、UPDATE文、DELETE文も同様に実行可能です。
SQLiteのデータ型は、INTEGER(符号付整数)、REAL(浮動小数点)、TEXT(テキスト)、BLOB(バイナリデータ)、 NULLのみとなっています。
データ登録
SQLiteDatabaseのexecSQLメソッドを使用してINSERT文も実行することできますが、 SQL文を使用しない方法もあります。
SQL文を使用しない場合は、ContentValuesクラスを使用して、データを設定します。
ContentValuesクラス
- 主なコンストラクタ
- ContentValues()
void | put(String key, String value) | keyにテーブルの列名、valueに値を指定します。 |
SQLiteDatabaseのinsertメソッドでデータの挿入をします。
long insert(String table, String nullColumnHack, ContentValues values)
- table : テーブル名
- nullColumnHack : 値を指定しない場合に「NULL」を登録したい列名(通常は、null)
- values : ContentValuesオブジェクト
データの更新
ContentValuesクラスを使用して、データを設定します。
SQLiteDatabaseのupdateメソッドでデータの更新をします。
int update(String table, ContentValues values, String whereClause, String[] whereArgs)
- table : テーブル名
- values : ContentValuesオブジェクト
- whereClause : 更新する条件式
- whereArgs : 第3引数の更新条件にプレースホルダ(?)を使用した場合の値を配列で指定
データ削除
SQLiteDatabaseのdeleteメソッドでデータを削除します。
int delete(String table, String whereClause, String[] whereArgs)
- table : テーブル名
- whereClause : 削除する条件式 (nullを指定すると全レコードが削除されます)。
- whereArgs : 第2引数の更新条件にプレースホルダ(?)を使用した場合の値を配列で指定
データ取得
データを格納するためのCursorクラスとSQLiteDatabaseのqueryメソッドを使用します。
Cursorクラス
abstract int | getCount() | レコード数の取得 |
abstract int | getColumnCount() | カラム数の取得 |
abstract boolean | moveToFirst() | カーソルで先頭のレコードを指し示す |
abstract boolean | moveToNext() | カーソル移動 |
abstract String | getString(int columnIndex) | String型の値取得 columnIndexは、カラム位置 |
abstract double | getDouble(int columnIndex) | double型の値取得 columnIndexは、カラム位置 |
abstract float | getFloat(int columnIndex) | float型の値取得 columnIndexは、カラム位置 |
abstract int | getInt(int columnIndex) | int型の値取得 columnIndexは、カラム位置 |
abstract long | getLong(int columnIndex) | long型の値取得 columnIndexは、カラム位置 |
abstract short | getShort(int columnIndex) | short型の値取得 columnIndexは、カラム位置 |
abstract void | close() | クローズ |
queryメソッド
SQLiteDatabaseのqueryメソッドでデータを取得します。
Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
- table : テーブル名
- columns : 取得する列名の配列(SELECT)
- selection : 選択条件(WHERE)
- selectionArgs : 第3引数の選択条件にプレースホルダ(?)を使用した場合の値を配列で指定
- groupBy : 集計条件(GROUP BY)
- having : 選択条件(HAVING)
- orderBy : ソート条件(ORDER BY)
トランザクション制御
Androidのトランザクション制御には、通常のSQLのようにrolbackがありません。
データベースにコミットをかけない限り、変更内容がデータベースに反映されないようになっています。
- トランザクション開始
void beginTransaction()メソッドを利用します。 - コミット
void setTransactionSuccessful()メソッドを利用します。 - トランザクション制御終了
void endTransaction()メソッドを利用します。
データベースクローズ
データベース関連の処理が終わったら、最後にcloseメソッドを使用して、データベースのクローズ処理を行います。
データベースサンプル(基本)
実行画面
1.起動時
2.データを入力し、登録ボタンを押下し、表示確認
3.次のデータを入力し、登録ボタンを押下
4.次データを入力し、登録ボタンを押下し、表示確認
現在3つのデータが登録されました。
5.次は、データを更新します。
データを入力した後、更新ボタンを押下します。
表示ボタンを押下し、確認すると赤線のデータが更新されています。
(注)今回のサンプルは、商品IDからの読み込みはありませんので、手動での入力となります。
6.次は、商品IDを入力後、削除ボタンを押下します。
表示ボタンを押下し、確認すると赤線のデータが削除されています。
DatabaseEx
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
android:text="商品ID:"
android:textSize="20sp" />
<EditText
android:id="@+id/s_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
android:text="商品名:"
android:textSize="20sp" />
<EditText
android:id="@+id/s_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10px"
android:layout_marginRight="10px"
android:text="価 格:"
android:textSize="20sp" />
<EditText
android:id="@+id/s_price"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/ins"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="登録" />
<Button
android:id="@+id/up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="更新" />
<Button
android:id="@+id/del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="削除" />
<Button
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="表示" />
</LinearLayout>
<TextView
android:id="@+id/res"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5px"
android:background="#ffffff"
android:gravity="center_horizontal"
android:textColor="#0000ff" />
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginTop="20dp" >
<TableLayout
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</TableLayout>
</ScrollView>
</LinearLayout>
DatabaseEx.java
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
public class DatabaseEx extends Activity implements OnClickListener {
private final static String DB_NAME = "test.db"; // データベース名
private final static String DB_TABLE = "product"; // テーブル名
private final static int DB_VERSION = 1; // バージョン
DBHelper helper = null;
SQLiteDatabase db = null;
int[] BUTTONS = { R.id.ins, R.id.up, R.id.del, R.id.show };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ボタンオブジェクト取得
for (int btnId : BUTTONS) {
Button btn = (Button) findViewById(btnId);
btn.setOnClickListener(this);
}
// DB作成
helper = new DBHelper(DatabaseEx.this);
}
@Override
public void onClick(View v) {
// メッセージ用
String message = "";
TextView res = (TextView) findViewById(R.id.res);
// EditTextオブジェクトの取得
EditText editId = (EditText) findViewById(R.id.s_id);
EditText editName = (EditText) findViewById(R.id.s_name);
EditText editPrice = (EditText) findViewById(R.id.s_price);
// テーブルレイアウトオブジェクトの取得
TableLayout t_layout = (TableLayout) findViewById(R.id.list);
// テーブルレイアウトオブジェクトのクリア
t_layout.removeAllViews();
// 該当DBオブジェクトの取得
db = helper.getWritableDatabase();
// 登録ボタン押下時
if (v.getId() == R.id.ins) {
// データ登録
try {
// トランザクション制御の開始
db.beginTransaction();
// 登録データ設定
ContentValues val = new ContentValues();
val.put("productid", editId.getText().toString());
val.put("name", editName.getText().toString());
val.put("price", editPrice.getText().toString());
// データ登録
db.insert(DB_TABLE, null, val);
// コミット
db.setTransactionSuccessful();
// トランザクション制御終了
db.endTransaction();
// EditTextの表示を初期化
editId.setText("");
editName.setText("");
editPrice.setText("");
// メッセージ設定
message = "データ登録が完了しました";
} catch (Exception e) {
// メッセージ設定
message = "データ登録に失敗しました";
Log.e("登録エラー", e.toString());
}
// 更新ボタン押下時
} else if (v.getId() == R.id.up) {
try {
// トランザクション制御開始
db.beginTransaction();
// 更新データ設定
ContentValues val = new ContentValues();
val.put("name", editName.getText().toString());
val.put("price", editPrice.getText().toString());
// データ更新
db.update(DB_TABLE, val, "productid=?", new String[] { editId.getText().toString() });
// コミット
db.setTransactionSuccessful();
// トランザクション制御終了
db.endTransaction();
// メッセージ設定
message = "データの更新をしました";
} catch (Exception e) {
message = "更新に失敗しました";
Log.e("更新", e.toString());
}
// 削除ボタン押下時
} else if (v.getId() == R.id.del) {
try {
// トランザクション開始
db.beginTransaction();
// データ削除
db.delete(DB_TABLE, "productid=?", new String[] { editId.getText().toString() });
// コミット
db.setTransactionSuccessful();
// トランザクション制御終了
db.endTransaction();
// メッセージ設定
message = "データを削除しました";
} catch (Exception e) {
message = "削除に失敗しました";
Log.e("削除", e.toString());
}
// 表示ボタン押下時
} else if (v.getId() == R.id.show) {
try {
// データの取得
db = helper.getReadableDatabase();
// 列名の定義
String[] columns = { "productid", "name", "price" };
// データの取得
Cursor cursor = db.query(DB_TABLE, columns, null, null, null,
null, "productid");
// テーブルレイアウトの表示範囲の設定
t_layout.setStretchAllColumns(true);
// テーブル一覧のヘッダ部設定
TableRow headrow = new TableRow(DatabaseEx.this);
TextView headeTxt1 = new TextView(DatabaseEx.this);
headeTxt1.setText("商品ID");
headeTxt1.setGravity(Gravity.CENTER_HORIZONTAL);
headeTxt1.setWidth(60);
TextView headText2 = new TextView(DatabaseEx.this);
headText2.setText("商品名");
headText2.setGravity(Gravity.CENTER_HORIZONTAL);
headText2.setWidth(100);
TextView headText3 = new TextView(DatabaseEx.this);
headText3.setText("価格");
headText3.setGravity(Gravity.CENTER_HORIZONTAL);
headText3.setWidth(60);
headrow.addView(headeTxt1);
headrow.addView(headText2);
headrow.addView(headText3);
t_layout.addView(headrow);
// 取得したデータをテーブル明細部に設定
while (cursor.moveToNext()) {
TableRow row = new TableRow(DatabaseEx.this);
TextView productIdText = new TextView(DatabaseEx.this);
productIdText.setText(cursor.getString(0));
productIdText.setGravity(Gravity.CENTER_HORIZONTAL);
TextView nameText = new TextView(DatabaseEx.this);
nameText.setText(cursor.getString(1));
nameText.setGravity(Gravity.CENTER_HORIZONTAL);
TextView prictTextView = new TextView(DatabaseEx.this);
prictTextView.setText(cursor.getString(2));
prictTextView.setGravity(Gravity.CENTER_HORIZONTAL);
row.addView(productIdText);
row.addView(nameText);
row.addView(prictTextView);
t_layout.addView(row);
// メッセージの設定
message = "データ取得をしました";
}
} catch (Exception e) {
message = "データ取得に失敗しました";
Log.e("表示", e.toString());
}
}
// DBオブジェクトクローズ
db.close();
// メッセージ表示
res.setText(message);
}
// データベースヘルパーの定義
private static class DBHelper extends SQLiteOpenHelper {
// コンストラクタ定義
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
// データベースの生成時処理
@Override
public void onCreate(SQLiteDatabase db) {
// テーブルの作成
// SQL文の定義
String sql = "create table if not exists "
+ DB_TABLE
+ "(productid text not null,name text not null,price integer default 0)";
// SQL実行
db.execSQL(sql);
}
// データベースのアップグレード時の処理
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// テーブル削除
db.execSQL("drop table if exists " + DB_TABLE);
// テーブル作成
onCreate(db);
}
}
}