Mit Room-DAOs auf Daten zugreifen

Wenn Sie die App-Daten in der Raum-Persistenzbibliothek speichern, interagieren Sie mit den gespeicherten Daten, indem Datenzugriffsobjekte (DAOs) definiert werden. Jeder DAO enthält Methoden, die abstrakten Zugriff auf die Datenbank Ihrer App bieten. Bei Kompilierung erstellt Room automatisch Implementierungen der von Ihnen definierten DAOs.

Indem Sie DAOs für den Zugriff auf die Datenbank Ihrer App anstelle von Query Buildern oder direkten können Sie die Trennung , eine kritische Architektur Prinzip. DAOs erleichtern es Ihnen auch, den Datenbankzugriff nachzuahmen, wenn Sie Ihre App testen.

Aufbau eines DAO

Sie können jeden DAO entweder als Schnittstelle oder als abstrakte Klasse definieren. Für einfache wird meist eine Schnittstelle genutzt. In beiden Fällen müssen Sie können Sie Ihre DAOs mit @Dao annotieren. DAOs verfügen über keine Eigenschaften, definieren aber eine oder mehrere Interaktionsmethoden. mit den Daten in der Datenbank Ihrer App.

Der folgende Code ist ein Beispiel für einen einfachen DAO, der Methoden für User-Objekte in eine Raumdatenbank einfügen, löschen und auswählen:

Kotlin

@Dao
interface UserDao {
    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)

    @Query("SELECT * FROM user")
    fun getAll(): List<User>
}

Java

@Dao
public interface UserDao {
    @Insert
    void insertAll(User... users);

    @Delete
    void delete(User user);

    @Query("SELECT * FROM user")
    List<User> getAll();
}

Es gibt zwei Arten von DAO-Methoden, die Datenbankinteraktionen definieren:

  • Praktische Methoden zum Einfügen, Aktualisieren und Löschen von Zeilen in ohne SQL-Code schreiben zu müssen.
  • Abfragemethoden, mit denen Sie Ihre eigene SQL-Abfrage schreiben können, um mit der Datenbank.

In den folgenden Abschnitten wird gezeigt, wie Sie beide Arten von DAO-Methoden verwenden, um die Datenbankinteraktionen definieren, die Ihre Anwendung benötigt.

Praktische Methoden

Der Chatroom enthält Anmerkungen zu Komfort, mit denen Methoden definiert werden, die einfache Einfügungen, Aktualisierungen und Löschungen, ohne dass Sie eine SQL-Anweisung schreiben müssen.

Wenn Sie komplexere Einfügungen, Aktualisierungen oder Löschungen verwenden Sie stattdessen eine Abfragemethode, um die Daten in der Datenbank abzufragen.

Einfügen

Mit der Anmerkung @Insert können Sie definieren Methoden, die ihre Parameter in die entsprechende Tabelle im Datenbank. Der folgende Code zeigt Beispiele für gültige @Insert-Methoden, die Fügen Sie ein oder mehrere User-Objekte in die Datenbank ein:

Kotlin

@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertUsers(vararg users: User)

    @Insert
    fun insertBothUsers(user1: User, user2: User)

    @Insert
    fun insertUsersAndFriends(user: User, friends: List<User>)
}

Java

@Dao
public interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);

    @Insert
    public void insertBothUsers(User user1, User user2);

    @Insert
    public void insertUsersAndFriends(User user, List<User> friends);
}

Jeder Parameter für eine @Insert-Methode muss entweder eine Instanz eines Rooms Data-Entity-Klasse annotiert mit @Entity oder eine Sammlung von Datenentitätsklasseninstanzen, von denen jede auf eine Datenbank verweist. Wenn die Methode @Insert aufgerufen wird, fügt Room Entitätsinstanz in die entsprechende Datenbanktabelle übergeben.

Wenn die Methode @Insert einen einzelnen Parameter empfängt, kann sie eine long zurückgeben. -Wert, der dem neuen rowId für das eingefügte Element entspricht. Wenn der Parameter ein Array oder eine Sammlung und gibt dann ein Array oder eine Sammlung von long-Werten, wobei jeder Wert den rowId für einen der eingefügten Elemente. Weitere Informationen zum Zurückgeben von rowId-Werten finden Sie in der Referenz. Dokumentation für @Insert Annotation und der SQLite-Dokumentation für rowid Tabellen.

Aktualisieren

Mit der Anmerkung @Update können Sie Methoden definieren, die bestimmte Zeilen in einer Datenbanktabelle aktualisieren. Gefällt mir @Insert-Methoden akzeptieren@Update Datenentitätsinstanzen als Parameter. Der folgende Code zeigt ein Beispiel für eine @Update-Methode, die versucht, Aktualisieren Sie ein oder mehrere User-Objekte in der Datenbank:

Kotlin

@Dao
interface UserDao {
    @Update
    fun updateUsers(vararg users: User)
}

Java

@Dao
public interface UserDao {
    @Update
    public void updateUsers(User... users);
}

Der Raum verwendet die primäre Instanz, Schlüssel entsprechend der bestandenen Entitätsinstanzen in Zeilen in der Datenbank. Wenn es keine Zeile mit der gleichen Primärschlüssel, werden im Raum keine Änderungen vorgenommen.

Mit der Methode @Update kann optional ein int-Wert zurückgegeben werden, der die Zahl angibt. die erfolgreich aktualisiert wurden.

Löschen

Mit der Anmerkung @Delete können Sie Methoden zum Löschen bestimmter Zeilen aus einer Datenbanktabelle definieren. Gefällt mir @Insert-Methoden akzeptieren@Delete Datenentitätsinstanzen als Parameter. Der folgende Code zeigt ein Beispiel für eine @Delete-Methode, die versucht, Löschen Sie ein oder mehrere User-Objekte aus der Datenbank:

Kotlin

@Dao
interface UserDao {
    @Delete
    fun deleteUsers(vararg users: User)
}

Java

@Dao
public interface UserDao {
    @Delete
    public void deleteUsers(User... users);
}

Der Raum verwendet die primäre Instanz, Schlüssel entsprechend der bestandenen Entitätsinstanzen in Zeilen in der Datenbank. Wenn es keine Zeile mit der gleichen Primärschlüssel, werden im Raum keine Änderungen vorgenommen.

Eine @Delete-Methode kann optional einen int-Wert zurückgeben, der die Anzahl der die erfolgreich gelöscht wurden.

Abfragemethoden

Mit der Anmerkung @Query können Sie SQL-Anweisungen schreiben und als DAO-Methoden verfügbar machen. Verwenden Sie diese Abfragemethoden, Daten aus der App-Datenbank abfragen oder komplexere Einfügungen, Aktualisierungen und Löschungen.

Room validiert SQL-Abfragen zur Kompilierungszeit. Wenn also ein Problem auftritt, Ihrer Abfrage ein Kompilierungsfehler statt eines Laufzeitfehlers.

Einfache Abfragen

Der folgende Code definiert eine Methode, die eine einfache SELECT-Abfrage verwendet. Alle User-Objekte in der Datenbank:

Kotlin

@Query("SELECT * FROM user")
fun loadAllUsers(): Array<User>

Java

@Query("SELECT * FROM user")
public User[] loadAllUsers();

In den folgenden Abschnitten wird gezeigt, wie Sie dieses Beispiel für eine typische Verwendung ändern können. Cases.

Teilmenge der Spalten einer Tabelle zurückgeben

Meistens müssen Sie nur eine Teilmenge der Spalten aus der Tabelle zurückgeben die Sie abfragen. Zum Beispiel könnten in Ihrer Benutzeroberfläche nur die ersten und und nicht jedes Detail über ihn. Speichern und die Ausführung von Abfragen optimieren. Fragen Sie nur die die Sie benötigen.

Mit Room können Sie ein einfaches Objekt aus jeder Ihrer Abfragen zurückgeben, solange können Sie den Satz der Ergebnisspalten dem zurückgegebenen Objekt zuordnen. Zum Beispiel haben Sie kann das folgende Objekt für den Vor- und Nachnamen eines Nutzers definieren:

Kotlin

data class NameTuple(
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

Java

public class NameTuple {
    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    @NonNull
    public String lastName;
}

Anschließend können Sie dieses einfache Objekt über Ihre Abfragemethode zurückgeben:

Kotlin

@Query("SELECT first_name, last_name FROM user")
fun loadFullName(): List<NameTuple>

Java

@Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();

Room erkennt, dass die Abfrage Werte für first_name und last_name-Spalten und dass diese Werte den Feldern im NameTuple. Wenn die Abfrage eine Spalte zurückgibt, die keinem Feld zugeordnet ist im zurückgegebenen Objekt enthält, zeigt Room eine Warnung an.

Einfache Parameter an eine Abfrage übergeben

Meistens müssen Ihre DAO-Methoden Parameter akzeptieren, Filtervorgänge ausführen. Raum unterstützt die Verwendung von Methodenparametern als Bindung in Ihren Abfragen verwenden.

Der folgende Code definiert beispielsweise eine Methode, die alle Nutzer ab einem bestimmten Alter:

Kotlin

@Query("SELECT * FROM user WHERE age > :minAge")
fun loadAllUsersOlderThan(minAge: Int): Array<User>

Java

@Query("SELECT * FROM user WHERE age > :minAge")
public User[] loadAllUsersOlderThan(int minAge);

Sie können auch mehrere Parameter übergeben oder auf denselben Parameter mehrere Mal in einer Abfrage verwenden, wie im folgenden Code gezeigt:

Kotlin

@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
fun loadAllUsersBetweenAges(minAge: Int, maxAge: Int): Array<User>

@Query("SELECT * FROM user WHERE first_name LIKE :search " +
       "OR last_name LIKE :search")
fun findUserWithName(search: String): List<User>

Java

@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
public User[] loadAllUsersBetweenAges(int minAge, int maxAge);

@Query("SELECT * FROM user WHERE first_name LIKE :search " +
       "OR last_name LIKE :search")
public List<User> findUserWithName(String search);

Sammlung von Parametern an eine Abfrage übergeben

Bei einigen Ihrer DAO-Methoden müssen Sie möglicherweise Parameter, die bis zur Laufzeit nicht bekannt sind. Der Raum erkennt, wenn ein Parameter stellt eine Sammlung dar und erweitert sie zur Laufzeit automatisch anhand der Anzahl der angegebenen Parameter.

Der folgende Code definiert beispielsweise eine Methode, die Informationen über Alle Nutzer aus einer Untergruppe von Regionen:

Kotlin

@Query("SELECT * FROM user WHERE region IN (:regions)")
fun loadUsersFromRegions(regions: List<String>): List<User>

Java

@Query("SELECT * FROM user WHERE region IN (:regions)")
public List<User> loadUsersFromRegions(List<String> regions);

Mehrere Tabellen abfragen

Einige Ihrer Abfragen erfordern möglicherweise Zugriff auf mehrere Tabellen, um den Messwert Ergebnis. Sie können JOIN-Klauseln in Ihren SQL-Abfragen verwenden, um auf mehr als in einer Tabelle.

Im folgenden Code wird eine Methode definiert, mit der drei Tabellen miteinander verknüpft werden, um Ergebnisse zurückzugeben. die Bücher, die derzeit einem bestimmten Nutzer ausgeliehen werden:

Kotlin

@Query(
    "SELECT * FROM book " +
    "INNER JOIN loan ON loan.book_id = book.id " +
    "INNER JOIN user ON user.id = loan.user_id " +
    "WHERE user.name LIKE :userName"
)
fun findBooksBorrowedByNameSync(userName: String): List<Book>

Java

@Query("SELECT * FROM book " +
       "INNER JOIN loan ON loan.book_id = book.id " +
       "INNER JOIN user ON user.id = loan.user_id " +
       "WHERE user.name LIKE :userName")
public List<Book> findBooksBorrowedByNameSync(String userName);

Sie können auch einfache Objekte definieren, um eine Teilmenge von Spalten aus mehreren zusammengeführten Tabellen, wie im Abschnitt Eine Teilmenge der Daten Spalten. Der folgende Code definiert einen DAO mit einer Methode, gibt die Namen der Nutzer und die Namen der Bücher zurück, die sie ausgeliehen haben:

Kotlin

interface UserBookDao {
    @Query(
        "SELECT user.name AS userName, book.name AS bookName " +
        "FROM user, book " +
        "WHERE user.id = book.user_id"
    )
    fun loadUserAndBookNames(): LiveData<List<UserBook>>

    // You can also define this class in a separate file.
    data class UserBook(val userName: String?, val bookName: String?)
}

Java

@Dao
public interface UserBookDao {
   @Query("SELECT user.name AS userName, book.name AS bookName " +
          "FROM user, book " +
          "WHERE user.id = book.user_id")
   public LiveData<List<UserBook>> loadUserAndBookNames();

   // You can also define this class in a separate file, as long as you add the
   // "public" access modifier.
   static class UserBook {
       public String userName;
       public String bookName;
   }
}

Multimap zurückgeben

In Raum 2.4 und höher können Sie auch Spalten aus mehreren Tabellen abfragen, ohne Definieren einer zusätzlichen Datenklasse durch Schreiben von Abfragemethoden, die eine Multimap -Objekt.

Sehen Sie sich das Beispiel aus dem Abschnitt Mehrere Tabellen abfragen an. Anstatt eine Liste von Instanzen einer benutzerdefinierten Datenklasse zurückzugeben, User und Book vorhanden ist, können Sie eine Zuordnung von User und Book direkt über Ihre Abfragemethode:

Kotlin

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<User, List<Book>>

Java

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id"
)
public Map<User, List<Book>> loadUserAndBookNames();

Wenn Ihre Abfragemethode eine Multimap zurückgibt, können Sie Abfragen schreiben, die GROUP BY-Klauseln, mit denen Sie die SQL-Funktionen für erweiterte Berechnungen und Filterfunktionen nutzen. Sie können beispielsweise Ihre loadUserAndBookNames()-Methode, um nur Nutzer mit drei oder mehr Büchern zurückzugeben gecheckt:

Kotlin

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id" +
    "GROUP BY user.name WHERE COUNT(book.id) >= 3"
)
fun loadUserAndBookNames(): Map<User, List<Book>>

Java

@Query(
    "SELECT * FROM user" +
    "JOIN book ON user.id = book.user_id" +
    "GROUP BY user.name WHERE COUNT(book.id) >= 3"
)
public Map<User, List<Book>> loadUserAndBookNames();

Wenn Sie nicht ganze Objekte zuordnen müssen, können Sie auch Zuordnungen zwischen Spalten in Ihrer Abfrage, indem Sie die Methode keyColumn und valueColumn-Attribute in einer @MapInfo-Anmerkung in Ihrem Query-Methode:

Kotlin

@MapInfo(keyColumn = "userName", valueColumn = "bookName")
@Query(
    "SELECT user.name AS username, book.name AS bookname FROM user" +
    "JOIN book ON user.id = book.user_id"
)
fun loadUserAndBookNames(): Map<String, List<String>>

Java

@MapInfo(keyColumn = "userName", valueColumn = "bookName")
@Query(
    "SELECT user.name AS username, book.name AS bookname FROM user" +
    "JOIN book ON user.id = book.user_id"
)
public Map<String, List<String>> loadUserAndBookNames();

Spezielle Rückgabetypen

Room bietet einige spezielle Rückgabetypen für die Integration in andere APIs Bibliotheken.

Abfragen mit Seitenumbruch mit der Paging-Bibliothek

Room unterstützt Abfragen mit nummerierten Seiten durch die Integration in das Paging Bibliothek. In Raum 2.3.0-alpha01 und höher ist, können DAOs PagingSource-Objekte mit Seite 3.

Kotlin

@Dao
interface UserDao {
  @Query("SELECT * FROM users WHERE label LIKE :query")
  fun pagingSource(query: String): PagingSource<Int, User>
}

Java

@Dao
interface UserDao {
  @Query("SELECT * FROM users WHERE label LIKE :query")
  PagingSource<Integer, User> pagingSource(String query);
}

Weitere Informationen zum Auswählen von Typparametern für PagingSource finden Sie unter Schlüssel und Wert auswählen .

Direkter Cursorzugriff

Wenn die Logik Ihrer Anwendung direkten Zugriff auf die Rückgabezeilen erfordert, können Sie Ihre DAO-Methoden, um ein Cursor-Objekt zurückzugeben enthalten, wie im folgenden Beispiel gezeigt:

Kotlin

@Dao
interface UserDao {
    @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
    fun loadRawUsersOlderThan(minAge: Int): Cursor
}

Java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
    public Cursor loadRawUsersOlderThan(int minAge);
}

Weitere Informationen

Weitere Informationen zum Zugriff auf Daten über Raum-DAOs finden Sie in den folgenden zusätzlichen Ressourcen:

Produktproben

Codelabs