[Android] SQLiteOpenHelperでデータベースを読み書きする

SQLiteデータベースの読み書きを勉強したメモ

参考:SQLiteOpenHelper | Android Developers

とりあえず書いてみたコード

  • SQLiteOpenHelperを継承したサブクラスを作成する。このサブクラスはデータベースを開いたり作ったりアップグレードしたり、データベース読み書きをするためのSQLiteDatabaseインスタンスを返したりする。

    package jp.fernweh;
    
    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.SQLiteDatabase.CursorFactory;
    import android.database.sqlite.SQLiteException;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.LinearLayout;
    import android.widget.Toast;
    
    public class Z095 extends Activity implements OnClickListener {
    
    Button mBtnWrite, mBtnRead;
    EditText mTextArea;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);
    setContentView(layout);
    
    mBtnWrite = new Button(this);
    mBtnWrite.setText("書き込む");
    mBtnWrite.setOnClickListener(this);
    layout.addView(mBtnWrite);
    
    mBtnRead = new Button(this);
    mBtnRead.setText("読み込む");
    mBtnRead.setOnClickListener(this);
    layout.addView(mBtnRead);
    
    mTextArea = new EditText(this);
    layout.addView(mTextArea);
    }
    
    // SQLiteOpenHelper は抽象クラスであり、
    // 2つの抽象メソッド onCreate, onUpgrade を持つため
    // これらを実装しなければならない。
    private class MySQLiteOpenHelper extends SQLiteOpenHelper {
    
    Context mContext;
    
    // 引数の無いコンストラクタが無いため作成しなければならない
    // コンストラクタで接続するデータベースを指定する
    public MySQLiteOpenHelper(Context context, String name,
        CursorFactory factory, int version) {
      super(context, name, factory, version);
      mContext = context;
    }
    
    @Override
    public void onCreate(SQLiteDatabase db) {
      // データベース作成時(
      // SQLDatabase#getWritableDatabase()
      // SQLDatabase#getReadableDatabase()
      // が成功したとき)にコールされる
    
      Toast.makeText(mContext, "onCreate", Toast.LENGTH_LONG).show();
    
      // データベース処理開始
      db.beginTransaction();
      try {
        // テーブル作成を実行
        db.execSQL("CREATE TABLE TABLE_NAME ( ID INTEGER PRIMARY KEY AUTOINCREMENT, FIELD_KEY);");
        db.setTransactionSuccessful();
      } finally {
        // データベース終了処理
        db.endTransaction();
      }
    
    }
    
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      // バージョンが上がったときにコールされる
      Toast.makeText(mContext, "onUpgrade", Toast.LENGTH_LONG).show();
    
      db.execSQL("DROP TABLE IF EXISTS test_table");
      onCreate(db);
    }
    
    @Override
    public void onOpen(SQLiteDatabase db) {
      // データベースが開かれたときに実行される
      // これの実装は任意
      super.onOpen(db);
      Toast.makeText(mContext, "onOpen", Toast.LENGTH_LONG).show();
    }
    
    }
    
    SQLiteOpenHelper mHelper;
    
    // スタート時と、onPause, onStop からの復帰時
    @Override
    protected void onResume() {
    super.onResume();
    
    Toast.makeText(this, "onResume", Toast.LENGTH_LONG).show();
    
    // SQLiteOpenHelperインスタンスを取得するための情報
    // コンテキスト
    Context CONTEXT = this;
    // データベース名 / メモリ上で使用する場合は null
    String DATABASE_NAME = "mydatabase.sqlite3";
    // CursorFactory : Cursorを作成するためのインスタンス
    CursorFactory CURSOR_FACTORY = null;
    // バージョン、1から始まる。
    // バージョンが変更されたときにコールされる
    // onUpgrade と onDowngrade の引数に渡される
    int DATABASE_VERSION = 1;
    
    // MySQLiteOpenHelperインスタンスを生成
    mHelper = new MySQLiteOpenHelper(CONTEXT, DATABASE_NAME,
        CURSOR_FACTORY, DATABASE_VERSION);
    }
    
    SQLiteDatabase mWritableDb;
    // SQLiteDatabase mReadableDb;
    
    // onPause時にデータベースを閉じる
    @Override
    protected void onPause() {
    super.onPause();
    
    Toast.makeText(this, "onPause", Toast.LENGTH_LONG).show();
    
    mHelper.close();
    
    if (mWritableDb != null) {
      Toast.makeText(this, "close mWritableDb", Toast.LENGTH_LONG).show();
      mWritableDb.close();
      // mReadableDb.close();
    }
    }
    
    @Override
    public void onClick(View v) {
    // SQLiteOpenHelper#getWritableDatabase() で
    // データベースを開いて、書き込み用の SQLiteDatabase# を取得
    // じゃなかった。こいつは読み書き両方できる
    // データベースが無ければ作成するが、この場合
    // SQLiteOpenHelper#onCreate(SQLiteDatabase db)
    // がコールされる
    if (mWritableDb == null || mWritableDb.isOpen() == false) {
      try {
        // mHelper.close();
        mWritableDb = mHelper.getWritableDatabase();
        // String text = mWritableDb.isOpen() ? "open": "not open" ;
        // Toast.makeText(this, text,
        // Toast.LENGTH_LONG).show();
      } catch (SQLiteException e) {
        Toast.makeText(this, "失敗 " + e.toString(), Toast.LENGTH_LONG)
            .show();
        return;
      }
    }
    
    // SQLiteOpenHelper#getReadableDatabase()
    // で読み込み用の SQLiteDatabase# を取得
    // データベースが無ければ作成して開くけども
    // ここのコードではデータベースが作成されることは無い。
    // それに上で 読み書き可能なインスタンスを取得しているので
    // そもそもこれ自体が不要なのでコメントアウトしておく
    /* mReadableDb = mHelper.getReadableDatabase() */
    
    if (v.equals(mBtnWrite)) {
      String text = mTextArea.getText().toString();
      writeDb(text);
    } else if (v.equals(mBtnRead)) {
      loadDb();
    }
    }
    
    private void writeDb(final String FIELD_VALUE) {
    // ContentValuesインスタンスに
    // データベースへ書き込む情報をセット
    ContentValues values = new ContentValues();
    values.put("ID", 1234567);
    values.put("FIELD_KEY", FIELD_VALUE);
    
    // 条件分岐 のための値を取得
    String data = readDb();
    if (data == null) {
      // 新規書き込みはINSERT
      // public long insert (String table, String nullColumnHack,
      // ContentValues values)
      mWritableDb.beginTransaction();
    
      try {
        mWritableDb.insert("TABLE_NAME", null, values);
        mWritableDb.setTransactionSuccessful();
      } finally {
        mWritableDb.endTransaction();
      }
    
      Toast.makeText(this, "INSERTしました", Toast.LENGTH_LONG).show();
    
    } else {
      // すでに存在する場合はUPDATE
      // public int update (String table, ContentValues values, String
      // whereClause, String[] whereArgs)
    
      mWritableDb.beginTransaction();
    
      try {
        mWritableDb.update("TABLE_NAME", values, "ID = ?",
            new String[] { "1234567" });
        mWritableDb.setTransactionSuccessful();
      } finally {
        mWritableDb.endTransaction();
      }
      Toast.makeText(this, "UPDATEしました", Toast.LENGTH_LONG).show();
    }
    }
    
    // データベースをSELECTする関数
    private String readDb() {
    // SQLiteDatabase#queryメソッドで取得
    // (rawQueryメソッドでも可能)
    // public Cursor query (String table, String[] columns, String
    // selection, String[] selectionArgs, String groupBy, String
    // having,String orderBy)
    // 検索結果はCursorインスタンスで返ってくる
    Cursor cur = null;
    
    try {
      String groupBy = null;
      String having = null;
      String orderBy = null;
    
      cur = mWritableDb.query("TABLE_NAME", new String[] { "FIELD_KEY" },
          "ID = ?", new String[] { "1234567" }, groupBy, having,
          orderBy);
    
      if (cur != null && cur.moveToFirst()) {
        String result = cur.getString(cur.getColumnIndex("FIELD_KEY"));
        return result;
      } else {
        return null;
      }
    } finally {
      if (cur != null) {
        cur.close();
      }
    }
    }
    
    private void loadDb() {
    String text = readDb();
    mTextArea.setText(text);
    }
    }
Share
関連記事