【AndroidでSQLiteを制する】SQLiteDatabase#queryについて
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
  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;
  }