Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Query

@Target([AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER]) class Query
androidx.room.Query

Marks a method in a Dao annotated class as a query method.

The value of the annotation includes the query that will be run when this method is called. This query is verified at compile time by Room to ensure that it compiles fine against the database.

The arguments of the method will be bound to the bind arguments in the SQL statement. See SQLite's binding documentation for details of bind arguments in SQLite.

Room only supports named bind parameter :name to avoid any confusion between the method parameters and the query bind parameters.

Room will automatically bind the parameters of the method into the bind arguments. This is done by matching the name of the parameters to the name of the bind arguments.

@Query("SELECT * FROM song WHERE release_year = :year")
      public abstract List<Song> findSongsByReleaseYear(int year);
  

As an extension over SQLite bind arguments, Room supports binding a list of parameters to the query. At runtime, Room will build the correct query to have matching number of bind arguments depending on the number of items in the method parameter.

@Query("SELECT * FROM song WHERE id IN(:songIds)")
      public abstract List<Song> findByIds(long[] songIds);
  
For the example above, if the songIds is an array of 3 elements, Room will run the query as: SELECT * FROM song WHERE id IN(?, ?, ?) and bind each item in the songIds array into the statement. One caveat of this type of binding is that only 999 items can be bound to the query, this is a limitation of SQLite ( see Section 9 of SQLite Limits).

There are 4 type of statements supported in Query methods: SELECT, INSERT, UPDATE, and DELETE.

For SELECT queries, Room will infer the result contents from the method's return type and generate the code that will automatically convert the query result into the method's return type. For single result queries, the return type can be any data object (also known as POJOs). For queries that return multiple values, you can use java.util.List or Array. In addition to these, any query may return Cursor or any query result can be wrapped in a LiveData.

INSERT queries can return void or long. If it is a long, the value is the SQLite rowid of the row inserted by this query. Note that queries which insert multiple rows cannot return more than one rowid, so avoid such statements if returning long.

UPDATE or DELETE queries can return void or int. If it is an int, the value is the number of rows affected by this query.

RxJava2 If you are using RxJava2, you can also return Flowable<T> or Publisher<T> from query methods. Since Reactive Streams does not allow null, if the query returns a nullable type, it will not dispatch anything if the value is null (like fetching an Entity row that does not exist). You can return Flowable<T[]> or Flowable<List<T>> to workaround this limitation.

Both Flowable<T> and Publisher<T> will observe the database for changes and re-dispatch if data changes. If you want to query the database without observing changes, you can use Maybe<T> or Single<T>. If a Single<T> query returns null, Room will throw EmptyResultSetException.

Additionally if the statement is an INSERT, UPDATE or DELETE then the return types, Single<T>, Maybe<T> and Completable are supported.

You can return arbitrary POJOs from your query methods as long as the fields of the POJO match the column names in the query result.

For example, if you have class:

class SongDuration {
      String name;
      @ColumnInfo(name = "duration")
      String length;
  }
  
You can write a query like this:
@Query("SELECT name, duration FROM song WHERE id = :songId LIMIT 1")
      public abstract SongDuration findSongDuration(int songId);
  
And Room will create the correct implementation to convert the query result into a SongDuration object. If there is a mismatch between the query result and the fields of the POJO, and as long as there is at least 1 field match, Room prints a RoomWarnings#CURSOR_MISMATCH warning and sets as many fields as it can.

Summary

Public constructors

<init>(value: String)

Marks a method in a Dao annotated class as a query method.

Properties

String

The SQLite query to be run.

Public constructors

<init>

Query(value: String)

Marks a method in a Dao annotated class as a query method.

The value of the annotation includes the query that will be run when this method is called. This query is verified at compile time by Room to ensure that it compiles fine against the database.

The arguments of the method will be bound to the bind arguments in the SQL statement. See SQLite's binding documentation for details of bind arguments in SQLite.

Room only supports named bind parameter :name to avoid any confusion between the method parameters and the query bind parameters.

Room will automatically bind the parameters of the method into the bind arguments. This is done by matching the name of the parameters to the name of the bind arguments.

@Query("SELECT * FROM song WHERE release_year = :year")
      public abstract List<Song> findSongsByReleaseYear(int year);
  

As an extension over SQLite bind arguments, Room supports binding a list of parameters to the query. At runtime, Room will build the correct query to have matching number of bind arguments depending on the number of items in the method parameter.

@Query("SELECT * FROM song WHERE id IN(:songIds)")
      public abstract List<Song> findByIds(long[] songIds);
  
For the example above, if the songIds is an array of 3 elements, Room will run the query as: SELECT * FROM song WHERE id IN(?, ?, ?) and bind each item in the songIds array into the statement. One caveat of this type of binding is that only 999 items can be bound to the query, this is a limitation of SQLite ( see Section 9 of SQLite Limits).

There are 4 type of statements supported in Query methods: SELECT, INSERT, UPDATE, and DELETE.

For SELECT queries, Room will infer the result contents from the method's return type and generate the code that will automatically convert the query result into the method's return type. For single result queries, the return type can be any data object (also known as POJOs). For queries that return multiple values, you can use java.util.List or Array. In addition to these, any query may return Cursor or any query result can be wrapped in a LiveData.

INSERT queries can return void or long. If it is a long, the value is the SQLite rowid of the row inserted by this query. Note that queries which insert multiple rows cannot return more than one rowid, so avoid such statements if returning long.

UPDATE or DELETE queries can return void or int. If it is an int, the value is the number of rows affected by this query.

RxJava2 If you are using RxJava2, you can also return Flowable<T> or Publisher<T> from query methods. Since Reactive Streams does not allow null, if the query returns a nullable type, it will not dispatch anything if the value is null (like fetching an Entity row that does not exist). You can return Flowable<T[]> or Flowable<List<T>> to workaround this limitation.

Both Flowable<T> and Publisher<T> will observe the database for changes and re-dispatch if data changes. If you want to query the database without observing changes, you can use Maybe<T> or Single<T>. If a Single<T> query returns null, Room will throw EmptyResultSetException.

Additionally if the statement is an INSERT, UPDATE or DELETE then the return types, Single<T>, Maybe<T> and Completable are supported.

You can return arbitrary POJOs from your query methods as long as the fields of the POJO match the column names in the query result.

For example, if you have class:

class SongDuration {
      String name;
      @ColumnInfo(name = "duration")
      String length;
  }
  
You can write a query like this:
@Query("SELECT name, duration FROM song WHERE id = :songId LIMIT 1")
      public abstract SongDuration findSongDuration(int songId);
  
And Room will create the correct implementation to convert the query result into a SongDuration object. If there is a mismatch between the query result and the fields of the POJO, and as long as there is at least 1 field match, Room prints a RoomWarnings#CURSOR_MISMATCH warning and sets as many fields as it can.

Properties

value

val value: String

The SQLite query to be run.

Return
String: The query to be run.