【AndroidでSQLiteを制する】SQLiteDatabase#queryについて

このエントリーを Google ブックマーク に追加
Pocket
[`yahoo` not found]

SQLデータベース内のテーブルに対してクエリを実行します。
今回はSQLiteDatabaseに定義されているクエリを行うコンビニエンスメソッドを使用します。

Activityを拡張して自由にデータを挿入する

SQLiteDatabase#insertを使用してデータをインサートするで作成した SQLiteActivityを拡張し、Bookテーブルに任意のデータを入力できるようにします。
また、入力したデータを一覧表示するListViewを設置します、まずはレイアウトファイルを定義します。
レイアウトで下記のViewを定義しました。
id クラス 説明
title EditText titleカラムに入れるデータを入力します。
subtitle EditText subtitleカラムに入れるデータを入力します。
insert Button 入力した内容でBookテーブルにデータを挿入するボタンです。
result ListView Bookテーブルの内容を表示するリストです。
  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:orientation="vertical">

      <EditText
          android:id="@+id/title"
          android:text="タイトル"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

      <EditText
          android:id="@+id/subtitle"
          android:text="サブタイトル"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

      <Button
          android:id="@+id/insert"
          android:text="追加"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />

      <ListView
          android:id="@+id/result"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>
  </LinearLayout>

続いてSQLiteActivityにViewの初期化処理を実装します。
SQLiteActivity#updateBookListはクエリを実行し、その結果をSQLiteActivity#showBookListに渡します。
SQLiteActivity#showBookListはListを渡すとListViewに表示します。
  public class SQLiteActivity extends AppCompatActivity {
      private ListView mListView;
      private EditText mTitleEditText;
      private EditText mSubTitleEditText;
      private Button mInsertButton;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_sqlite);
          mListView = (ListView) findViewById(R.id.result);
          mTitleEditText = (EditText) findViewById(R.id.title);
          mSubTitleEditText = (EditText) findViewById(R.id.subtitle);
          mSubTitleEditText.setText("サブタイトル (" + new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime()) + ")");
          mInsertButton = (Button) findViewById(R.id.insert);
          mInsertButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  BookDTO bookDTO = new BookDTO();
                  bookDTO.setTitle(mTitleEditText.getText().toString());
                  bookDTO.setSubtitle(mSubTitleEditText.getText().toString());
                  insertBook(bookDTO);
                  updateBookList();
              }
          });
      }

      @Override
      protected void onResume() {
          super.onResume();
          updateBookList();
      }

      private void updateBookList() {
        // ここにクエリを実装します
        List<BookDTO> bookDTOList = new ArrayList();
        showBookList(bookDTOList);
      }

      private void insertBook(BookDTO book) {
          long rowId = BookDAO.insert(getApplicationContext() , book);
          Toast.makeText(this, "rowId:" + rowId , Toast.LENGTH_SHORT).show();
      }

      private void insertOrThrowBook(BookDTO book) {
          long rowId = BookDAO.insertOrThrow(getApplicationContext() , book);
          Toast.makeText(this, "rowId:" + rowId , Toast.LENGTH_SHORT).show();
      }

      private void showBookList(List<BookDTO> bookDTOList) {
          final List<Map<String, String>> list = new ArrayList<>();
          for (BookDTO bookDTO : bookDTOList) {
              Map<String, String> map = new HashMap<>();
              map.put("title", bookDTO.getTitle());
              map.put("subtitle", bookDTO.getSubtitle());
              list.add(map);
          }

          SimpleAdapter adapter = new SimpleAdapter(
                  this,
                  list,
                  android.R.layout.simple_list_item_2,
                  new String[] {"title", "subtitle"},
                  new int[] {android.R.id.text1, android.R.id.text2}
          );
          mListView.setAdapter(adapter);
      }
  }

SQLiteDatabase#queryのオーバーロード

SQLiteDatabase#queryには4つのオーバーロードがあります。
オーバーロード1
String table クエリに対象テーブルを指定します。
この引数がFROM句で使用されるので「 FROM table 」が生成されます。
String[] columns クエリの結果に含まれるカラムを複数指定します。
「SELECT columns[0],columns[1]….」が生成されます。
nullを指定すると「SELECT *」になりすべてのカラムが含まれます。
String selection WHERE句を指定します。
「[カラム名] = ? AND [カラム名] = ? 」のようにクエリに条件を設定します。
?はselectionArgsで指定します。
WHERE句が不要な場合はnullを指定してください。
String[] selectionArgs String selectionで指定した「?」を埋めるための文字列を配列で指定できます。
「?」の数よりも配列の要素数が多い場合は例外が発生します。
WHERE句に「?」が存在しない場合はnullを指定してください。
String groupBy GROUP BY句を設定します。
GROUP BY句が不要な場合はnullを設定してください。
String having HAVING句を設定します。
HAVING句が不要な場合はnullを設定してください。
String orderBy ORDER BY句を設定します。
ORDER BY句が不要な場合はnullを設定してください。

オーバーロード2
String table クエリに対象テーブルを指定します。
この引数がFROM句で使用されるので「 FROM table 」が生成されます。
String[] columns クエリの結果に含まれるカラムを複数指定します。
「SELECT columns[0],columns[1]….」が生成されます。
nullを指定すると「SELECT *」になりすべてのカラムが含まれます。
String selection WHERE句を指定します。
「[カラム名] = ? AND [カラム名] = ? 」のようにクエリに条件を設定します。
?はselectionArgsで指定します。
WHERE句が不要な場合はnullを指定してください。
String[] selectionArgs String selectionで指定した「?」を埋めるための文字列を配列で指定できます。
「?」の数よりも配列の要素数が多い場合は例外が発生します。
WHERE句に「?」が存在しない場合はnullを指定してください。
String groupBy GROUP BY句を設定します。
GROUP BY句が不要な場合はnullを設定してください。
String having HAVING句を設定します。
HAVING句が不要な場合はnullを設定してください。
String orderBy ORDER BY句を設定します。
ORDER BY句が不要な場合はnullを設定してください。
String limit LIMIT句を設定します、OFFSET句もここに書きます。
LIMIT句が不要な場合はnullを設定してください。

オーバーロード3
boolean distinct trueを指定すると出力するデータから重複行を削除します。
重複行を削除しない場合はfalseを指定します。
String table クエリに対象テーブルを指定します。
この引数がFROM句で使用されるので「 FROM table 」が生成されます。
String[] columns クエリの結果に含まれるカラムを複数指定します。
「SELECT columns[0],columns[1]….」が生成されます。
nullを指定すると「SELECT *」になりすべてのカラムが含まれます。
String selection WHERE句を指定します。
「[カラム名] = ? AND [カラム名] = ? 」のようにクエリに条件を設定します。
?はselectionArgsで指定します。
WHERE句が不要な場合はnullを指定してください。
String[] selectionArgs String selectionで指定した「?」を埋めるための文字列を配列で指定できます。
「?」の数よりも配列の要素数が多い場合は例外が発生します。
WHERE句に「?」が存在しない場合はnullを指定してください。
String groupBy GROUP BY句を設定します。
GROUP BY句が不要な場合はnullを設定してください。
String having HAVING句を設定します。
HAVING句が不要な場合はnullを設定してください。
String orderBy ORDER BY句を設定します。
ORDER BY句が不要な場合はnullを設定してください。
String limit LIMIT句を設定します、OFFSET句もここに書きます。
LIMIT句が不要な場合はnullを設定してください。

オーバーロード4
boolean distinct trueを指定すると出力するデータから重複行を削除します。
重複行を削除しない場合はfalseを指定します。
String table クエリに対象テーブルを指定します。
この引数がFROM句で使用されるので「 FROM table 」が生成されます。
String[] columns クエリの結果に含まれるカラムを複数指定します。
「SELECT columns[0],columns[1]….」が生成されます。
nullを指定すると「SELECT *」になりすべてのカラムが含まれます。
String selection WHERE句を指定します。
「[カラム名] = ? AND [カラム名] = ? 」のようにクエリに条件を設定します。
?はselectionArgsで指定します。
WHERE句が不要な場合はnullを指定してください。
String[] selectionArgs String selectionで指定した「?」を埋めるための文字列を配列で指定できます。
「?」の数よりも配列の要素数が多い場合は例外が発生します。
WHERE句に「?」が存在しない場合はnullを指定してください。
String groupBy GROUP BY句を設定します。
GROUP BY句が不要な場合はnullを設定してください。
String having HAVING句を設定します。
HAVING句が不要な場合はnullを設定してください。
String orderBy ORDER BY句を設定します。
ORDER BY句が不要な場合はnullを設定してください。
String limit LIMIT句を設定します、OFFSET句もここに書きます。
LIMIT句が不要な場合はnullを設定してください。
CancellationSignal cancellationSignal クエリを途中で中断するキャンセル要求やキャンセル時のコールバックを管理するクラスです。
このインスタンスを経由して外部からクエリを中断することが可能になります。
CancellationSignal#cancelを実行するとOperationCanceledExceptionがスローされます。

Cursorを処理する

データベースから返却されるデータはCursor クラスを経由してデータにアクセスすることになります。
BookDAOにCursorからデータを取り出してListに変換するメソッドを実装します。
  private static List<BookDTO> convertCursorToDTO(Cursor cursor) {
      List<BookDTO> ret = new ArrayList<>();
      while(cursor.moveToNext()){
          BookDTO bookDTO = new BookDTO();
          int columnIndex = cursor.getColumnIndex(LoadToSQLiteMasterContract.Book._ID);
          if(columnIndex != -1) {
              bookDTO.setId(cursor.getInt(columnIndex));
          }
          columnIndex = cursor.getColumnIndex(COLUMN_NAME_TITLE);
          if(columnIndex != -1) {
              bookDTO.setTitle(cursor.getString(columnIndex));
          }
          columnIndex = cursor.getColumnIndex(COLUMN_NAME_SUBTITLE);
          if(columnIndex != -1) {
              bookDTO.setSubtitle(cursor.getString(columnIndex));
          }
          ret.add(bookDTO);
      }
      return ret;
  }