public @interface

RawQuery

implements java.lang.annotation.Annotation

 androidx.room.RawQuery

Overview

Marks a method in a Dao annotated class as a raw query method where you can pass the query as a SupportSQLiteQuery.

  @Dao
 interface RawDao {
    @RawQuery
   Song getSongViaQuery(SupportSQLiteQuery query);
 }

 // Usage of RawDao
 SimpleSQLiteQuery query = new SimpleSQLiteQuery(
     "SELECT * FROM Song WHERE id = ? LIMIT 1",
     new Object[]{ songId});
 Song song = rawDao.getSongViaQuery(query);
 

Room will generate the code based on the return type of the function and failure to pass a proper query will result in a runtime failure or an undefined result.

If you know the query at compile time, you should always prefer Query since it validates the query at compile time and also generates more efficient code since Room can compute the query result at compile time (e.g. it does not need to account for possibly missing columns in the response).

On the other hand, RawQuery serves as an escape hatch where you can build your own SQL query at runtime but still use Room to convert it into objects.

RawQuery methods must return a non-void type. If you want to execute a raw query that does not return any value, use RoomDatabase#query methods.

RawQuery methods can only be used for read queries. For write queries, use RoomDatabase.getOpenHelper().getWritableDatabase().

Observable Queries:

RawQuery methods can return observable types but you need to specify which tables are accessed in the query using the RawQuery.observedEntities() field in the annotation.

  @Dao
 interface RawDao {
    @RawQuery(observedEntities = Song.class)
   LiveData<List<Song>> getSongs(SupportSQLiteQuery query);
 }

 // Usage of RawDao
 LiveData<List<Song>> liveSongs = rawDao.getSongs(
     new SimpleSQLiteQuery("SELECT * FROM song ORDER BY name DESC"));
 
Returning POJOs:

RawQueries can also return plain old java objects, similar to Query methods.

 public class NameAndReleaseYear {
   final String name;
    @ColumnInfo(name = "release_year")
   final int year;

   public NameAndReleaseYear(String name, int year) {
     this.name = name;
     this.year = year;
   }
 }

  @Dao
 interface RawDao {
    @RawQuery
   NameAndReleaseYear getNameAndReleaseYear(SupportSQLiteQuery query);
 }

 // Usage of RawDao
 NameAndReleaseYear result = rawDao.getNameAndReleaseYear(
     new SimpleSQLiteQuery("SELECT * FROM song WHERE id = ?", new Object[]{songId}))
 

POJOs with Embedded Fields:

RawQuery methods can return POJOs that include Embedded fields as well.

 public class SongAndArtist {
    @Embedded
   public Song song;
    @Embedded
   public Artist artist;
 }

  @Dao
 interface RawDao {
    @RawQuery
   SongAndArtist getSongAndArtist(SupportSQLiteQuery query);
 }

 // Usage of RawDao
 SongAndArtist result = rawDao.getSongAndArtist(
     new SimpleSQLiteQuery("SELECT * FROM Song, Artist WHERE Song.artistId = Artist.id LIMIT 1"))
 
Relations:

RawQuery return types can also be objects with Relations.

 public class AlbumAndSongs {
      @Embedded
     public Album album;
      @Relation(parentColumn = "id", entityColumn = "albumId")
     public List<Song> pets;
 }

  @Dao
 interface RawDao {
    @RawQuery
   List<AlbumAndSongs> getAlbumAndSongs(SupportSQLiteQuery query);
 }

 // Usage of RawDao
 List<AlbumAndSongs> result = rawDao.getAlbumAndSongs(
     new SimpleSQLiteQuery("SELECT * FROM album"));
 

Summary

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.room;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Marks a method in a {@link Dao} annotated class as a raw query method where you can pass the
 * query as a {@link androidx.sqlite.db.SupportSQLiteQuery SupportSQLiteQuery}.
 * <pre>
 * {@literal @}Dao
 * interface RawDao {
 *   {@literal @}RawQuery
 *   Song getSongViaQuery(SupportSQLiteQuery query);
 * }
 *
 * // Usage of RawDao
 * SimpleSQLiteQuery query = new SimpleSQLiteQuery(
 *     "SELECT * FROM Song WHERE id = ? LIMIT 1",
 *     new Object[]{ songId});
 * Song song = rawDao.getSongViaQuery(query);
 * </pre>
 * <p>
 * Room will generate the code based on the return type of the function and failure to
 * pass a proper query will result in a runtime failure or an undefined result.
 * <p>
 * If you know the query at compile time, you should always prefer {@link Query} since it validates
 * the query at compile time and also generates more efficient code since Room can compute the
 * query result at compile time (e.g. it does not need to account for possibly missing columns in
 * the response).
 * <p>
 * On the other hand, {@code RawQuery} serves as an escape hatch where you can build your own
 * SQL query at runtime but still use Room to convert it into objects.
 * <p>
 * {@code RawQuery} methods must return a non-void type. If you want to execute a raw query that
 * does not return any value, use {@link androidx.room.RoomDatabase#query
 * RoomDatabase#query} methods.
 * <p>
 * RawQuery methods can only be used for read queries. For write queries, use
 * {@link androidx.room.RoomDatabase#getOpenHelper
 * RoomDatabase.getOpenHelper().getWritableDatabase()}.
 * <p>
 * <b>Observable Queries:</b>
 * <p>
 * {@code RawQuery} methods can return observable types but you need to specify which tables are
 * accessed in the query using the {@link #observedEntities()} field in the annotation.
 * <pre>
 * {@literal @}Dao
 * interface RawDao {
 *   {@literal @}RawQuery(observedEntities = Song.class)
 *   LiveData&lt;List&lt;Song&gt;&gt; getSongs(SupportSQLiteQuery query);
 * }
 *
 * // Usage of RawDao
 * LiveData&lt;List&lt;Song&gt;&gt; liveSongs = rawDao.getSongs(
 *     new SimpleSQLiteQuery("SELECT * FROM song ORDER BY name DESC"));
 * </pre>
 * <b>Returning POJOs:</b>
 * <p>
 * RawQueries can also return plain old java objects, similar to {@link Query} methods.
 * <pre>
 * public class NameAndReleaseYear {
 *   final String name;
 *   {@literal @}ColumnInfo(name = "release_year")
 *   final int year;
 *
 *   public NameAndReleaseYear(String name, int year) {
 *     this.name = name;
 *     this.year = year;
 *   }
 * }
 *
 * {@literal @}Dao
 * interface RawDao {
 *   {@literal @}RawQuery
 *   NameAndReleaseYear getNameAndReleaseYear(SupportSQLiteQuery query);
 * }
 *
 * // Usage of RawDao
 * NameAndReleaseYear result = rawDao.getNameAndReleaseYear(
 *     new SimpleSQLiteQuery("SELECT * FROM song WHERE id = ?", new Object[]{songId}))
 * </pre>
 * <p>
 * <b>POJOs with Embedded Fields:</b>
 * <p>
 * {@code RawQuery} methods can return POJOs that include {@link Embedded} fields as well.
 * <pre>
 * public class SongAndArtist {
 *   {@literal @}Embedded
 *   public Song song;
 *   {@literal @}Embedded
 *   public Artist artist;
 * }
 *
 * {@literal @}Dao
 * interface RawDao {
 *   {@literal @}RawQuery
 *   SongAndArtist getSongAndArtist(SupportSQLiteQuery query);
 * }
 *
 * // Usage of RawDao
 * SongAndArtist result = rawDao.getSongAndArtist(
 *     new SimpleSQLiteQuery("SELECT * FROM Song, Artist WHERE Song.artistId = Artist.id LIMIT 1"))
 * </pre>
 *
 * <b>Relations:</b>
 * <p>
 * {@code RawQuery} return types can also be objects with {@link Relation Relations}.
 * <pre>
 * public class AlbumAndSongs {
 *     {@literal @}Embedded
 *     public Album album;
 *     {@literal @}Relation(parentColumn = "id", entityColumn = "albumId")
 *     public List&lt;Song&gt; pets;
 * }
 *
 * {@literal @}Dao
 * interface RawDao {
 *   {@literal @}RawQuery
 *   List&lt;AlbumAndSongs&gt; getAlbumAndSongs(SupportSQLiteQuery query);
 * }
 *
 * // Usage of RawDao
 * List&lt;AlbumAndSongs&gt; result = rawDao.getAlbumAndSongs(
 *     new SimpleSQLiteQuery("SELECT * FROM album"));
 * </pre>
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface RawQuery {
    /**
     * Denotes the list of entities which are accessed in the provided query and should be observed
     * for invalidation if the query is observable.
     * <p>
     * The listed classes should either be annotated with {@link Entity} or they should reference to
     * at least 1 Entity (via {@link Embedded} or {@link Relation}).
     * <p>
     * Providing this field in a non-observable query has no impact.
     * <pre>
     * {@literal @}Dao
     * interface RawDao {
     *   {@literal @}RawQuery(observedEntities = Song.class)
     *   LiveData&lt;List&lt;User&gt;&gt; getUsers(String query);
     * }
     * LiveData&lt;List&lt;Song&gt;&gt; liveSongs = rawDao.getUsers(
     *     "SELECT * FROM song ORDER BY name DESC");
     * </pre>
     *
     * @return List of entities that should invalidate the query if changed.
     */
    Class<?>[] observedEntities() default {};
}