通常のRoom
からSqlite
を使用するようにアプリを移行していますが、問題が発生しているのは、ユーザーが構成できるorderbyステートメントを持つクエリがいくつかあることです。リストの順序を表示する方法を変更します。
Roomでは動的なorderbyステートメントが許可されていないため、orderbyステートメントごとに個別のクエリを実行する必要があるようです。
誰かがこの問題を回避するより良い方法を見つけたので、1つのクエリステートメントを使用できます。変更されるのはorder by句だけですが、私の場合は、基本的に同じ15個の追加のクエリステートメントを記述する必要がありますか?
Room 1.1には、この問題を解決するために使用できるRawQuery
があります。
@Dao
interface RawDao {
@RawQuery
User getUserViaQuery(SupportSQLiteQuery query);
}
SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ? LIMIT 1",
new Object[]{userId});
User user2 = rawDao.getUserViaQuery(query);
https://developer.Android.com/reference/Android/Arch/persistence/room/RawQuery
私は今同じ問題に直面しています。実行できることは、CASEを使用することです。
SELECT * FROM Table
ORDER BY
CASE WHEN :parameter = 1 THEN Column END ASC,
CASE WHEN :parameter = 2 THEN Column2 END DESC
ただし、ViewModel
も使用していると想定しているため、毎回再初期化する必要があります。この方法は、15個のクエリを作成するよりも少し優れていると思いますが、それほどコンパクトではないかもしれません。
この answer にも良い例がありますが、論理が逆になっていると思います。
tyczj がすでに提案しているように、RawQuery
を使用できます。さらに、SimpleSQLiteQuery
をDAOに移動することもできるため、DAOの外部にSQLステートメントはありません。
DAOは、抽象クラスを介して定義することもできます。これにより、SimpleSQLiteQuery
を実行するメソッドを追加できます。
例:
@DAO
public abstract class UserDao {
@RawQuery
public abstract List<User> getUsersViaRawQuery(SupportSQLiteQuery query);
public List<User> getUsersOrderBy(String column) {
String statement = "SELECT * FROM user ORDER BY " + column + " ASC";
SupportSQLiteQuery query = new SimpleSQLiteQuery(statement, new Object[]{});
return getUsersViaRawQuery(query);
}
}
列パラメーターは、特定の値のみを許可する列挙型に置き換えることもできます。
例:
private static String createOrderByString(Order order) {
switch (order) {
case NAME:
return "ORDER BY first_name ASC, last_name ASC";
case AGE:
return "ORDER BY age DESC";
default:
return "";
}
}
OurDaoのメソッドではパラメーターを使用できません。
@Query("SELECT * FROM sometable order by :orderClause DESC")
List<Islem> findOneUserName(String orderClause);//didn't work
このクエリパラメータは、SQLインジェクションを回避するためのwhereパラメータでのみ使用されます。