Quando usi la libreria di persistenza della stanza per archiviare i dati dell'app, interagisci con i dati archiviati definendo oggetti di accesso ai dati o DAO. Ogni DAO include metodi che offrono accesso astratto al database dell'app. Al momento della compilazione volta, Room genera automaticamente le implementazioni dei DAO che definisci.
Usando DAO per accedere al database dell'app anziché tramite Query Builder o dirigere query, puoi conservare la separazione di sicurezza, un'architettura di base dell'IA. I DAO semplificano anche la simulazione dell'accesso al database quando testare l'app.
Anatomia di un DAO
Puoi definire ogni DAO come interfaccia o classe astratta. Per le versioni di base
casi d'uso, di solito usi un'interfaccia. In ogni caso, devi sempre
annota i DAO con @Dao
. DAO
non hanno proprietà, ma definiscono uno o più metodi di interazione
con i dati del database dell'app.
Il codice riportato di seguito è un esempio di un DAO semplice che definisce i metodi per
inserimento, eliminazione e selezione di User
oggetti in un database delle stanze:
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(); }
Esistono due tipi di metodi DAO che definiscono le interazioni con i database:
- Metodi pratici che ti consentono di inserire, aggiornare ed eliminare righe senza scrivere codice SQL.
- Metodi di query che ti consentono di scrivere la tua query SQL per interagire con per configurare un database.
Le seguenti sezioni mostrano come utilizzare entrambi i tipi di metodi DAO per e definire le interazioni con il database necessarie alla tua app.
Metodi pratici
La stanza virtuale fornisce annotazioni pratiche per la definizione di metodi semplici inserimenti, aggiornamenti ed eliminazioni senza che sia necessario scrivere un'istruzione SQL.
Se hai bisogno di definire inserimenti, aggiornamenti o eliminazioni più complessi o per eseguire query sui dati nel database, utilizza invece un metodo query.
Inserisci
L'annotazione @Insert
ti consente di
definire metodi che inseriscono i propri parametri nella tabella appropriata del
per configurare un database. Il seguente codice mostra esempi di metodi @Insert
validi che
Inserisci uno o più oggetti User
nel database:
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); }
Ogni parametro per un metodo @Insert
deve essere un'istanza di una room
classe entità di dati annotata con
@Entity
o una raccolta di istanze della classe entità dati, ciascuna delle quali
punta a un database. Quando viene chiamato un metodo @Insert
, la stanza virtuale inserisce ogni
ha passato l'istanza dell'entità alla tabella di database corrispondente.
Se il metodo @Insert
riceve un singolo parametro, può restituire un long
che corrisponde al nuovo rowId
per l'elemento inserito. Se il parametro è un
un array o una raccolta, quindi restituisce un array o una raccolta
di long
valori, con ogni valore come rowId
per uno dei valori inseriti
elementi. Per scoprire di più sulla restituzione dei valori rowId
, consulta il riferimento
documentazione di @Insert
e la documentazione di SQLite per rowid
tabelle.
Aggiorna
L'annotazione @Update
ti consente di
definiscono metodi che aggiornano righe specifiche in una tabella di database. Mi piace
I metodi @Insert
, @Update
accettano le istanze entità dati come parametri.
Il codice seguente mostra un esempio di metodo @Update
che tenta di
aggiorna uno o più oggetti User
nel database:
Kotlin
@Dao interface UserDao { @Update fun updateUsers(vararg users: User) }
Java
@Dao public interface UserDao { @Update public void updateUsers(User... users); }
La stanza virtuale utilizza il chiave affinché corrisponda a quella passata istanze di entità in righe nel database. Se non è presente una riga con lo stesso chiave primaria, la stanza non apporta modifiche.
Un metodo @Update
può restituire facoltativamente un valore int
che indica il numero
di righe aggiornate correttamente.
Elimina
L'annotazione @Delete
ti consente di
definiscono i metodi che eliminano righe specifiche da una tabella di database. Mi piace
I metodi @Insert
, @Delete
accettano le istanze entità dati come parametri.
Il codice seguente mostra un esempio di metodo @Delete
che tenta di
Elimina uno o più oggetti User
dal database:
Kotlin
@Dao interface UserDao { @Delete fun deleteUsers(vararg users: User) }
Java
@Dao public interface UserDao { @Delete public void deleteUsers(User... users); }
La stanza virtuale utilizza il chiave affinché corrisponda a quella passata istanze di entità in righe nel database. Se non è presente una riga con lo stesso chiave primaria, la stanza non apporta modifiche.
Un metodo @Delete
può restituire facoltativamente un valore int
che indica il numero di
righe eliminate correttamente.
Metodi di query
L'annotazione @Query
ti consente di
scrivere istruzioni SQL ed esporle come metodi DAO. Utilizza questi metodi di query per
interroga i dati dal database della tua app o quando devi eseguire attività
inserimenti, aggiornamenti ed eliminazioni.
La stanza virtuale convalida le query SQL al momento della compilazione. Ciò significa che se c'è un problema della query, si verifica un errore di compilazione anziché un errore di runtime.
Query semplici
Il seguente codice definisce un metodo che utilizza una semplice query SELECT
per restituire
tutti gli oggetti User
nel database:
Kotlin
@Query("SELECT * FROM user") fun loadAllUsers(): Array<User>
Java
@Query("SELECT * FROM user") public User[] loadAllUsers();
Le seguenti sezioni mostrano come modificare questo esempio per l'utilizzo tipico d'uso diversi.
Restituire un sottoinsieme delle colonne di una tabella
La maggior parte delle volte devi restituire solo un sottoinsieme delle colonne della tabella su cui stai eseguendo query. Ad esempio, nella UI potrebbero essere visualizzati solo i primi due il cognome di un utente invece di ogni suo dettaglio. Per risparmiare risorse e semplifichino l'esecuzione della query, esegui la query solo campi necessari.
Room ti consente di restituire un oggetto semplice da qualsiasi query, purché puoi mappare l'insieme di colonne dei risultati all'oggetto restituito. Ad esempio, può definire l'oggetto seguente in cui inserire nome e cognome di un utente:
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; }
Quindi, puoi restituire questo semplice oggetto dal tuo metodo di query:
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();
La stanza virtuale comprende che la query restituisce valori per first_name
e
last_name
colonne e che questi valori possono essere mappati ai campi in
NameTuple
corso. Se la query restituisce una colonna che non corrisponde a un campo
nell'oggetto restituito, la stanza virtuale mostra un avviso.
Trasmettere parametri semplici a una query
La maggior parte delle volte, i metodi DAO devono accettare parametri in modo da poter eseguire operazioni di filtro. La stanza virtuale supporta l'utilizzo di parametri del metodo come associazione parametri nelle tue query.
Ad esempio, il seguente codice definisce un metodo che restituisce tutti gli utenti al di sopra di una determinata età:
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);
Puoi anche passare più parametri o fare riferimento a più parametri allo stesso volte in una query, come illustrato nel codice che segue:
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);
Passare una raccolta di parametri a una query
Alcuni dei tuoi metodi DAO potrebbero richiedere il passaggio di un numero variabile conosciuti fino al runtime. La stanza capisce quando un parametro rappresenta una raccolta e la espande automaticamente in fase di runtime in base di parametri forniti.
Ad esempio, il seguente codice definisce un metodo che restituisce informazioni su per tutti gli utenti di un sottoinsieme di regioni:
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);
Eseguire query su più tabelle
Alcune query potrebbero richiedere l'accesso a più tabelle per calcolare il
o il risultato finale. Puoi utilizzare le clausole JOIN
nelle query SQL per fare riferimento a più di
una tabella.
Il codice seguente definisce un metodo che unisce tre tabelle da restituire i libri attualmente in prestito a uno specifico utente:
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);
È inoltre possibile definire oggetti semplici per restituire un sottoinsieme di colonne da più come descritto nella sezione Restituisci un sottoinsieme dei dati di una tabella Colonne. Il seguente codice definisce un DAO con un metodo che restituisce i nomi degli utenti e i nomi dei libri che hanno preso in prestito:
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; } }
Restituire una mappa multipla
Nella stanza 2.4 e successive, puoi anche eseguire query sulle colonne da più tabelle senza la definizione di una classe di dati aggiuntiva scrivendo metodi di query che restituiscono un multimap.
Considera l'esempio della sezione Esegui query su più tabelle.
Invece di restituire un elenco di istanze di una classe di dati personalizzata che contiene
accoppiamenti di User
e Book
istanze, puoi restituire una mappatura di User
e
Book
direttamente dal tuo metodo di query:
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();
Quando il metodo di query restituisce una mappa multipla, puoi scrivere query che utilizzano
GROUP BY
, che ti consentono di sfruttare le funzionalità di SQL per
calcoli e filtri avanzati. Ad esempio, puoi modificare
loadUserAndBookNames()
metodo per restituire solo gli utenti con tre o più libri
check-out:
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();
Se non è necessario mappare interi oggetti, puoi anche restituire mappature tra
colonne specifiche della query impostando
keyColumn
e
Attributi valueColumn
in un'annotazione @MapInfo
sul tuo
:
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();
Tipi di resi speciali
Room fornisce alcuni tipi di resi speciali per l'integrazione con altre API librerie.
Query impaginate con la libreria Paging
La stanza virtuale supporta le query impaginate tramite l'integrazione con il
libreria di Google. Nella stanza 2.3.0-alpha01 e
superiore, i DAO possono restituire
PagingSource
oggetti da utilizzare
con Paging 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); }
Per ulteriori informazioni sulla scelta dei parametri del tipo per un PagingSource
, consulta
Seleziona chiave e valore
tipi di annunci personalizzati.
Accesso diretto al cursore
Se la logica della tua app richiede l'accesso diretto alle righe restituite, puoi scrivere
i tuoi metodi DAO per restituire un Cursor
come mostrato nell'esempio seguente:
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); }
Risorse aggiuntive
Per scoprire di più sull'accesso ai dati utilizzando i DAO delle stanze, consulta le di risorse: