実行時にクエリを作成することは可能ですか?
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
limit
部分はオプションです。つまり、制限なしまたは制限なしで同じクエリを実行できる必要があります。
前のケースでは、制限部分がある場合とない場合の2つの静的クエリを作成することが可能で、毎回適切なクエリを使用できます。ただし、フィルターの作成など、より複雑な状況に対処しなければならない場合があります。
その場合、前の例とは異なり、複数のオプション部分があります。書籍の表の場合、書籍が属するカテゴリ、著者名、価格帯、出版日などに応じてフィルタリングを行う必要がある場合があります。これらの部分のすべての組み合わせで静的クエリを作成することはほとんど不可能です。
私の経験では(短い)ルームを使用することは不可能であり、ルームの制限のためではなく、@CommonsWareによって暗黙的にコメントされているように、SQLiteの制限です。 2つのクエリが必要なので、DAOには2つのメソッドが必要です。
私は次のようなものを持っているでしょう:
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title ")
List<IPlaylist> searchPlaylists(String playlistTitle);
次に、バイパスを行う別の場所:
if (limit.isPresent()) {
return playlistDao.searchPlaylists(title, limit.get());
} else {
return playlistDao.searchPlaylists(title);
}
それが現時点で考えることができる最良の選択肢です。
複数のクエリを記述する代わりに、limit句に負の値を渡します。クエリに変更がある場合は、両方のクエリを更新する必要があるため、エラーが発生しやすくなります。
公式ドキュメント->LIMIT式が負の値に評価される場合、返される行数に上限はありません。ここで見つけることができます https://sqlite.org/lang_select.html 制限条項セクションを読んでください。
だから私はこのようなことをするだろう、
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
List<IPlaylist> searchPlaylists(String playlistTitle, int limit);
フィルタを適用したくない場合は負の値を渡します。
return playlistDao.searchPlaylists(title, limit.isPresent() ? limit.get() : -1)
私の場合はうまくいっています。
更新済み[2018年12月21日]
場合kotlinを使用している場合は、デフォルト値を使用します。
@JvmOverloads
@Query("SELECT * FROM playlist " +
"WHERE playlist_title LIKE '% :playlistTitle %' " +
"GROUP BY playlist_title " +
"ORDER BY playlist_title " +
"LIMIT :limit")
fun searchPlaylists(playlistTitle: String, limit: Int = -1): List<IPlaylist>
@JvmOverloads
Javaとの互換性を確保します。 Java用に2つの個別のメソッドを生成します。
ルームは @RawQuery
アノテーションをサポートし、実行時にクエリを構築します。
通常の@RawQuery
の代わりに@RawQuery
アノテーションでDAOメソッドをマークします。
@Dao
interface BooksDao{
@RawQuery
List<Book> getBooks(SupportSQLiteQuery query);
}
Roomは、セキュリティとコンパイル時の検証のために準備されたステートメントを使用します。したがって、クエリを構築する際に、クエリ文字列とバインドパラメータを別々に保存する必要があります。
この例では、クエリ文字列に変数queryString
を使用し、バインドパラメーターにargs
を使用します。
(テキストエディタを使用してコードを記述したことに注意してください。そのため、タイプミスや単純な構文エラーが発生する可能性があります。
// Query string
String queryString = new String();
// List of bind parameters
List<Object> args = new ArrayList();
boolean containsCondition = false;
// Beginning of query string
queryString += "SELECT * FROM BOOKS";
// Optional parts are added to query string and to args upon here
if(!authorName.isEmpty()){
queryString += " WHERE";
queryString += " author_name LIKE ?%";
args.add(authorName);
containsCondition = true;
}
if(fromDate!=null){
if (containsCondition) {
queryString += " AND";
} else {
queryString += " WHERE";
containsCondition = true;
}
queryString += " publication_date AFTER ?";
args.add(fromDate.getTime());
}
if(toDate!=null){
if (containsCondition) {
queryString += " AND";
} else {
queryString += " WHERE";
containsCondition = true;
}
queryString += " publication_date BEFORE ?";
args.add(toDate.getTime());
}
// End of query string
queryString += ";";
SimpleSQLiteQuery query = new SimpleSQLiteQuery(queryString, args.toArray());
List<Book> result = booksDao.getBooks(query);
Query
と同様に、RawQuery
は未加工のカーソル、エンティティ、POJO、および埋め込みフィールドを持つPOJOを返すことをサポートしますRawQuery
はリレーションをサポートしますルームにはオプションのパラメータのようなものはありませんが、クエリを文字列として渡すことができる@RawQueryアノテーションがあり、ランタイムでSQLクエリを作成できます。これはあなたに役立つと思います。
公式ドキュメントの例を次に示します。
@Dao
interface RawDao {
@RawQuery
User getUser(String query);
}
そして、それを使用する方法は次のとおりです。
User user = rawDao.getUser("SELECT * FROM User WHERE id = 3 LIMIT 1");
重要: RawQueryメソッドは非void型を返す必要があります
重要:これはRoom 1.1.0-alpha3で利用可能です
SupportSQLiteQueryを使用します。
https://developer.Android.com/reference/Android/Arch/persistence/db/SupportSQLiteQuery
最新リリース1.1.1では、SupportSQLiteQueryが使用されるようになりました。
型付きバインディングを使用したクエリ。タイプセーフなパラメーターをバインドできるため、rawQuery(String、String [])の代わりにこのAPIを使用する方が適切です。
@Dao
interface RawDao {
@RawQuery(observedEntities = User.class)
LiveData<List<User>> getUsers(SupportSQLiteQuery query);
}
使用法:
LiveData<List<User>> liveUsers = rawDao.getUsers( new
SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));
グラドルを1.1.1に更新する
implementation 'Android.Arch.persistence.room:runtime:1.1.1'
implementation 'Android.Arch.lifecycle:extensions:1.1.1'
annotationProcessor "Android.Arch.persistence.room:compiler:1.1.1"
注:1.1.1にアップグレードし、SupportSQLiteQueryの代わりにStringを使用している場合、
エラーが表示されます:
RawQueryは文字列を渡すことを許可しなくなりました。 Android.Arch.persistence.db.SupportSQLiteQueryを使用してください。
上記のようにSupportSQLiteQueryを使用すると、問題が解決します。
注:SupportSQLiteQueryクエリパラメーターを必ず渡すと、このエラーが発生します。
RawQueryメソッドには、String型またはSupportSQLiteQuery型のパラメーターが1つだけ必要です。
もっとシンプルに。 2つの変数を使用するwhere句を使用した例を示します。次のようにします:
@Query("SELECT * FROM Student WHERE stdName1= :myname AND stdId1=:myid")
List<Student> fetchAllData(String myname,int myid);
stdName1およびstdId1は列名です