Çoklu-çoklu ilişkileri tanımlama ve sorgulama

İki varlık arasındaki çoktan çok ilişki, ana varlığın her örneğinin sıfır veya daha fazla alt varlık örneğine karşılık geldiği ve bunun tersinin de geçerli olduğu bir ilişkidir.

Müzik akışı uygulaması örneğinde, kullanıcı tanımlı oynatma listelerindeki şarkıları göz önünde bulundurun. Her oynatma listesi birçok şarkı içerebilir ve her şarkı birçok farklı oynatma listesinde yer alabilir. Bu nedenle, Playlist öğesi ile Song öğesi arasında çoka çok ilişki vardır.

Veritabanınızdaki çoktan çok ilişkiyi tanımlamak ve sorgulamak için aşağıdaki adımları uygulayın:

  1. İlişkiyi tanımlayın: Çoka-çok ilişkisini temsil etmek için öğeleri ve ilişkili öğeyi (çapraz referans tablosu) oluşturun.
  2. Varlıkları sorgulama: İlgili varlıkları nasıl sorgulamak istediğinizi belirleyin ve amaçlanan çıktıyı temsil edecek veri sınıfları oluşturun.

İlişkiyi tanımlama

Çoktan çoğa ilişki tanımlamak için öncelikle iki varlığınızın her biri için bir sınıf oluşturun. Çoktan çoka ilişkiler, diğer ilişki türlerinden farklıdır. Çünkü genellikle alt öğede üst öğeye referans verilmez. Bunun yerine, iki öğe arasında ilişkilendirilmiş bir öğeyi veya çapraz referans tablosunu temsil eden üçüncü bir sınıf oluşturun. Çapraz başvuru tablosunda, tabloda temsil edilen çoktan çoğa ilişkideki her varlığın birincil anahtarı için sütunlar olmalıdır. Bu örnekte, çapraz referans tablosundaki her satır, referans verilen şarkının referans verilen oynatma listesinde yer aldığı bir Playlist örneği ile bir Song örneğinin eşleşmesine karşılık gelir.

Kotlin

@Entity
data class Playlist(
    @PrimaryKey val playlistId: Long,
    val playlistName: String
)

@Entity
data class Song(
    @PrimaryKey val songId: Long,
    val songName: String,
    val artist: String
)

@Entity(primaryKeys = ["playlistId", "songId"])
data class PlaylistSongCrossRef(
    val playlistId: Long,
    val songId: Long
)

Java

@Entity
public class Playlist {
    @PrimaryKey public long playlistId;
    public String playlistName;
}

@Entity
public class Song {
    @PrimaryKey public long songId;
    public String songName;
    public String artist;
}

@Entity(primaryKeys = {"playlistId", "songId"})
public class PlaylistSongCrossRef {
    public long playlistId;
    public long songId;
}

Varlıkları sorgulama

Bir sonraki adım, bu ilgili öğeleri nasıl sorgulamak istediğinize bağlıdır.

  • Oynatma listelerini ve her oynatma listesi için ilgili şarkıların listesini sorgulamak istiyorsanız tek bir Playlist nesnesi ve oynatma listesinin içerdiği tüm Song nesnelerinin listesini içeren yeni bir veri sınıfı oluşturun.
  • Şarkıları ve her şarkı için ilgili oynatma listelerinin listesini sorgulamak istiyorsanız tek bir Song nesnesi ve şarkının yer aldığı tüm Playlist nesnelerinin listesini içeren yeni bir veri sınıfı oluşturun.

Her iki durumda da, Playlist öğesi ile Song öğesi arasındaki ilişkiyi sağlayan çapraz referans öğesini tanımlamak için bu sınıfların her birindeki @Relation açıklamasında associateBy özelliğini kullanarak öğeler arasındaki ilişkiyi modelleyin.

Kotlin

data class PlaylistWithSongs(
    @Embedded val playlist: Playlist,
    @Relation(
         parentColumn = "playlistId",
         entityColumn = "songId",
         associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val songs: List<Song>
)

data class SongWithPlaylists(
    @Embedded val song: Song,
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = Junction(PlaylistSongCrossRef::class)
    )
    val playlists: List<Playlist>
)

Java

public class PlaylistWithSongs {
    @Embedded public Playlist playlist;
    @Relation(
         parentColumn = "playlistId",
         entityColumn = "songId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Song> songs;
}

public class SongWithPlaylists {
    @Embedded public Song song;
    @Relation(
         parentColumn = "songId",
         entityColumn = "playlistId",
         associateBy = @Junction(PlaylistSongCrossref.class)
    )
    public List<Playlist> playlists;
}

Son olarak, uygulamanızın ihtiyaç duyduğu sorgu işlevini kullanıma sunmak için DAO sınıfına bir yöntem ekleyin.

  • getPlaylistsWithSongs: Bu yöntem, veritabanını sorgular ve sonuç olarak elde edilen tüm PlaylistWithSongs nesnelerini döndürür.
  • getSongsWithPlaylists: Bu yöntem, veritabanını sorgular ve sonuç olarak elde edilen tüm SongWithPlaylists nesnelerini döndürür.

Bu yöntemlerin her birinde Room'un iki sorgu çalıştırması gerekir. Bu nedenle, tüm işlemin atomik olarak gerçekleştirilmesi için her iki yönteme de @Transaction ek açıklamasını ekleyin.

Kotlin

@Transaction
@Query("SELECT * FROM Playlist")
fun getPlaylistsWithSongs(): List<PlaylistWithSongs>

@Transaction
@Query("SELECT * FROM Song")
fun getSongsWithPlaylists(): List<SongWithPlaylists>

Java

@Transaction
@Query("SELECT * FROM Playlist")
public List<PlaylistWithSongs> getPlaylistsWithSongs();

@Transaction
@Query("SELECT * FROM Song")
public List<SongWithPlaylists> getSongsWithPlaylists();