ホーム >  Android > データベース

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() クローズ

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がありません。
データベースにコミットをかけない限り、変更内容がデータベースに反映されないようになっています。

  1. トランザクション開始
    void beginTransaction()メソッドを利用します。
  2. コミット
    void setTransactionSuccessful()メソッドを利用します。
  3. トランザクション制御終了
    void endTransaction()メソッドを利用します。

データベースクローズ

データベース関連の処理が終わったら、最後にcloseメソッドを使用して、 データベースのクローズ処理を行います。

データベースサンプル(基本)

database1

1.起動時


database2

2.データを入力し、登録ボタンを押下し、表示確認

database3

3.次のデータを入力し、登録ボタンを押下


database4

4.次データを入力し、登録ボタンを押下し、表示確認
  現在3つのデータが登録されました。


database5

5.次は、データを更新します。
  データを入力した後、更新ボタンを押下します。
  表示ボタンを押下し、確認すると赤線のデータが更新されています。

(注)今回のサンプルは、商品IDからの読み込みはありませんので、手動での入力となります。


database6

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, nullnullnull,
            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);
      }
    }
}