Una relazione one-to-many tra due entità è una relazione in cui ogni istanza dell'entità padre corrisponde a zero o più istanze dell'entità figlio, ma ogni istanza dell'entità figlio può corrispondere a una sola istanza dell'entità padre.
Nell'esempio dell'app di streaming musicale, supponiamo che l'utente possa organizzare i brani in playlist. Ogni utente può creare tutte le playlist che vuole, ma ogni playlist viene creata da un solo utente. Esiste quindi una relazione one-to-many tra l'entità User e l'entità Playlist.
Per definire ed eseguire query sulle relazioni one-to-many nel database:
- Definisci la relazione: crea classi per entrambe le entità, con l'entità figlio che fa riferimento alla chiave primaria dell'entità padre.
- Esegui query sulle entità: modella la relazione in una nuova classe di dati e implementa una funzione per recuperare i dati correlati.
Definisci la relazione
Per definire una relazione one-to-many, crea prima una classe per ogni entità. Come in una relazione one-to-one, l'entità figlio deve includere una variabile che fa riferimento alla chiave primaria dell'entità padre.
@Entity data class User( @PrimaryKey val userId: Long, val name: String, val age: Int ) @Entity data class Playlist( @PrimaryKey val playlistId: Long, val userCreatorId: Long, val playlistName: String )
Esegui query sulle entità
Per eseguire query sull'elenco degli utenti e sulle playlist corrispondenti, devi prima modellare la relazione one-to-many tra le due entità.
Per modellare la relazione, crea una nuova classe di dati. Ogni istanza di questa classe contiene un'istanza dell'entità padre e un elenco di tutte le istanze dell'entità figlio corrispondenti.
Aggiungi l'annotazione @Relation alla proprietà che rappresenta l'elenco
delle entità figlio. Imposta parentColumns sul nome della colonna di chiave primaria dell'entità padre
e imposta entityColumns sul nome della colonna dell'entità figlio
che fa riferimento alla chiave primaria dell'entità padre.
data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["userId"], entityColumns = ["userCreatorId"] ) val playlists: List<Playlist> )
Infine, aggiungi una funzione alla classe Data Access Object (DAO) che restituisce tutte le istanze della classe di dati che accoppiano l'entità padre e l'entità figlio.
Aggiungi l'annotazione @Transaction in modo che Room esegua l'intera operazione
in modo atomico. Questa annotazione è necessaria perché la funzione richiede a Room di eseguire due query.
@Transaction @Query("SELECT * FROM User") suspend fun getUsersWithPlaylists(): List<UserWithPlaylists>
Chiavi composite
Se definisci la relazione utilizzando chiavi composite, specifica più colonne in parentColumns e entityColumns. L'ordine delle colonne in parentColumns deve corrispondere all'ordine delle colonne in entityColumns.
@Entity(primaryKeys = ["firstName", "lastName"]) data class User( val firstName: String, val lastName: String, val age: Int ) @Entity data class Playlist( @PrimaryKey val playlistId: Long, val userFirstName: String, val userLastName: String, val playlistName: String ) data class UserWithPlaylists( @Embedded val user: User, @Relation( parentColumns = ["firstName", "lastName"], entityColumns = ["userFirstName", "userLastName"] ) val playlists: List<Playlist> )