web-dev-qa-db-ja.com

Android Room:Order Byが機能しない

私は新しいAndroid ORM Roomを使用しています。次の問題に直面しました。引数付きのORDER BYを使用するクエリは機能しません。

ORDER BYのパラメーターから入力されたフィールドを使用する場合、機能しません。それは何もソートしません。

@Query("SELECT * FROM User ORDER BY :orderBY ASC")
List<User> sortedFind(String orderBY);

ただし、クエリにORDER BY列を直接配置して結果を並べ替えると、期待どおりに機能します。

@Query("SELECT * FROM User ORDER BY name ASC")
List<User> sortedFind();

Android Roomのバグですか、それとも何か間違っていますか?

28
Sirelon

何が起こっているのか

パラメーターとして@Daoメソッドに渡すことができる値は、クエリ文字列ではなく値のみです。この理由(私は信じています)は、SQLインジェクションの問題を防ぐためです。

なぜそうなのか

たとえば、クエリSELECT * emails WHERE uid = ?を実行してから、値を"1 OR WHERE isAdmin = true"に設定します。これにより、ユーザーはデータベースで独自のカスタムクエリを実行し、必要な処理を実行できます。

私の解決策

私もこの問題に遭遇しました。ここに私の solution へのリンクがあります。

私のソリューションには2つの部分があります。最初にDynamicQueryserviceが入力に基づいてクエリ文字列と値配列を生成し、次に生のクエリを実行してCursorを返します。第二に、Cursor2POJOマッパーなので、クラスのカーソルマッピングを何度も記述したり、潜在的なメンテナンスの問題を導入したりする必要がありません。クラスに注釈を追加するだけで(部屋の列名と一致する)、libが残りを処理します。

カーソルマッパーを独自の library に分割しました。ご参考までに、お気軽に使用してください(readmeが明確でない場合や、コメントにバグがある場合は作成してください) 。

追伸私のライブラリは、注釈が現在RetentionPolicy.CLASSとして設定されているため、リフレクションからアクセスできないため、Room @ColumnInfoを使用して列名を取得できません。 (Google課題トラッカーに追加 https://issuetracker.google.com/issues/6372094

7
Jack Dalton

ランタイムクエリには@RawQueryアノテーションとSupportSQLiteQueryクラスを使用する必要があります

ダオで:

 @RawQuery
 List<Objects> runtimeQuery(SupportSQLiteQuery sortQuery);

データを取得するには:

String query ="SELECT * FROM User ORDER BY " + targetField + " ASC";
List<Objects> users = appDatabase.daoUser().runtimeQuery(new SimpleSQLiteQuery(query));
2
Shahab Saalami

いずれかの列の名前を参照して、データを昇順でのみ配置できます。プログラムでDaoメソッドに値を渡すことはできません

0
VIKAS SHARMA

問題は、SQLステートメントの一部を渡すことですが、Roomはそれをクエリパラメーターのように扱います。

必要に応じて、SQLiteが管理するAndroidプラットフォームおよびサポートしている状況のようなオープンソースライブラリであるKripton Persistence Libraryを使用してみてください。

KriptonはDAOパターンでも動作するため、コンセプトは非常に似ています。ニーズに合った例を書くだけです:

モデルクラスがある場合:

@BindType
public class User {
    public long id;
    public String name;
    public String username;
    public String email;
    public Address address;
    public String phone;
    public String website;
    public Company company;
}

dAO定義:

@BindDao(User.class)
public interface UserDao {
    @BindSqlInsert
    void insert(User bean);

   @BindSqlSelect
   List<User> sortedFind(@BindSqlDynamicOrderBy String orderBy);
}

およびデータソース定義:

@BindDataSource(daoSet={UserDao.class}, fileName = "kripton.quickstart.db", generateAsyncTask = true)
public interface QuickStartDataSource {
}

Kriptonは、コンパイル時にすべてのコードがデータベースで動作するために必要なものを生成します。 Kriptonでタスクを達成するには、次のようなコードを記述する必要があります。

BindQuickStartDataSource ds = BindQuickStartDataSource.instance();
// execute operation in a transaction
ds.execute(new BindQuickStartDataSource.SimpleTransaction() {
  @Override
  public boolean onExecute(BindQuickStartDaoFactory daoFactory) throws Throwable 
  {
    UserDaoImpl dao = daoFactory.getUserDao();
    dao.sortedFind("name asc");
    return true;
  }
});

上記のコードを実行すると、logcatで生成されたログが表示されます。

database OPEN READ_AND_WRITE_OPENED (connections: 1)
SELECT id, name, username, email, address, phone, website, company FROM user ORDER BY name asc
Rows found: 0
database CLOSED (READ_AND_WRITE_OPENED) (connections: 0)

クリプトンは、明らかに静的順序とその他の多くの機能をサポートしています(2015年に開発を開始しました)。

Kripton Persistence Libraryの詳細:

0
xcesco