Nesneler arasındaki ilişkileri tanımlama

SQLite ilişkisel bir veritabanı olduğundan, Google Analytics 4'teki varlıklarından oluşur. Ancak çoğu nesne ilişkisel eşleme kitaplığı, nesneler birbirine referansta bulunuyorsa Oda, bunu açıkça yasaklar. Hakkında bilgi edinmek için daha fazla bilgi için Odanın, neden karar vermediğini nesne başvurularına izin verme başlıklı makaleye bakın.

İki olası yaklaşım

Oda'da, varlıklar arasındaki bir ilişkiyi tanımlamanın ve sorgulamanın iki yolu vardır: veya mevcut bir yerleştirilmiş nesneler veya çoklu harita döndürmeli ilişkisel sorgu yöntemi türü.

Orta veri sınıfı

Orta düzey veri sınıfı yaklaşımında, dönüşüm modellemeyi ilişkilendirmeniz gerekir. Bu veri sınıfı, eşlemeleri saklar Bir varlığın örnekleri ile başka bir varlığın örnekleri arasında, yerleştirilmiş nesneler'i tıklayın. Sorgu yöntemleriniz, daha sonra bu veri sınıfını kullanmanız gerekir.

Örneğin, kitaplık kullanıcılarını temsil eden bir UserBook veri sınıfı tanımlayabilirsiniz. kontrol edebilir ve bu kitapların listesini almak için bir sorgu yöntemi Veritabanından UserBook örnek:

Kotlin

@Dao
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>>
}

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();
}

public class UserBook {
    public String userName;
    public String bookName;
}

Çoklu eşleme dönüş türleri

Çoklu eşleme dönüş türü yaklaşımında, herhangi bir ek eşleme türü tanımlamanız gerekmez. veri sınıfları. Bunun yerine Şunun için çoklu eşleme dönüş türü: yöntemini belirleyin ve yöntem ile kurduğunuz ilişki SQL sorgunuzda varlıklarınız arasında otomatik olarak geçiş yapın.

Örneğin, aşağıdaki sorgu yöntemi User ve Book eşlemesini döndürür. Kütüphane kullanıcılarını belirli kitaplara göz atmış olarak temsil eden örnekler:

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();

Yaklaşım belirleyin

Oda, bu yaklaşımların her ikisini de destekler. Bu nedenle, en iyi yaklaşıma sahip olmanız gerekir. Bu bölümde, iki nedenden birini tercih edebilirsiniz.

Orta düzey veri sınıfı yaklaşımı sayesinde karmaşık SQL yazmaktan kaçınabilirsiniz. ancak bu durum, ek veri sınıflarından bahsedeceğiz. Kısacası, çoklu harita dönüş türü Yaklaşımı, SQL sorgularınızın daha fazla iş yapmasını gerektirir ve orta düzeyde veriler daha fazla iş yapmak için kodunuzun kullanılmasını gerektirir.

Orta düzey veri sınıfları kullanmak için özel bir nedeniniz yoksa çoklu eşleme dönüş türü yaklaşımını kullanmanızı önerir. Şu konu hakkında daha fazla bilgi edinmek için: daha fazla bilgi için Bir çoklu eşleme.

Bu kılavuzun geri kalanında, orta düzey veri sınıfı yaklaşımı kullanabilirsiniz.

Yerleştirilmiş nesneler oluşturma

Bazen bir varlığı veya veri nesnesini nesne birden fazla öğe içerse bile veritabanı mantığınızda tutarlı bir bütün alanları. Böyle durumlarda, @Embedded ayrıştırmak istediğiniz bir nesneyi temsil eden ek açıklama alt alanlara sahip olur. Ardından, Google Ads'de yerleşik olarak bulunan alanları sütun oluşturabilirsiniz.

Örneğin, User sınıfınız şunu içeren Address türünde bir alan içerebilir: street, city, state ve postCode. Oluşturulan sütunları tabloda ayrı ayrı depolamak için tablodaki bir User sınıfındaki, Address alanı @Embedded, olduğu gibi aşağıdaki kod snippet'inde gösterilmektedir:

Kotlin

data class Address(
    val street: String?,
    val state: String?,
    val city: String?,
    @ColumnInfo(name = "post_code") val postCode: Int
)

@Entity
data class User(
    @PrimaryKey val id: Int,
    val firstName: String?,
    @Embedded val address: Address?
)

Java

public class Address {
    public String street;
    public String state;
    public String city;

    @ColumnInfo(name = "post_code") public int postCode;
}

@Entity
public class User {
    @PrimaryKey public int id;

    public String firstName;

    @Embedded public Address address;
}

Bir User nesnesini temsil eden tablo, aşağıdakilerin bulunduğu sütunları içerir adlar: id, firstName, street, state, city ve post_code.

Bir öğede aynı türde birden çok yerleşik alan varsa her birini değerini ayarlayarak prefix Ardından oda, sağlanan değeri her sütunun başına ekler adını yazın.

Bire bir ilişkileri tanımlayın

İki varlık arasındaki bire bir ilişki, her öğenin örneği, alt öğenin tam olarak bir örneğine karşılık gelir varlık, tersi de geçerlidir.

Örneğin, kullanıcının bulunduğu bir kitaplığa sahip bir müzik yayın uygulaması düşünün. şarkılarına yer verir. Her kullanıcının yalnızca bir kitaplığı ve her kullanıcının tam olarak bir kullanıcıya karşılık gelir. Bu nedenle, bire bir User varlığı ile Library varlığı arasındaki ilişki.

Bire bir ilişki tanımlamak için önce ikiniz için birer sınıf oluşturun varlıklarından oluşur. Varlıklardan biri diğer varlığın birincil anahtarına referans veren bir değişken eklemeyin.

Kotlin

@Entity
data class User(
    @PrimaryKey val userId: Long,
    val name: String,
    val age: Int
)

@Entity
data class Library(
    @PrimaryKey val libraryId: Long,
    val userOwnerId: Long
)

Java

@Entity
public class User {
    @PrimaryKey public long userId;
    public String name;
    public int age;
}

@Entity
public class Library {
    @PrimaryKey public long libraryId;
    public long userOwnerId;
}

Kullanıcı listesini ve ilgili kitaplıkları sorgulamak için önce bu iki varlık arasındaki birebir ilişki modelini kullanır. Bunu yapmak için bir Her örneğin üst varlığın bir örneğini içerdiği yeni veri sınıfı ve alt varlığın karşılık gelen örneğidir. @Relation ekleyin parentColumn değeri şu şekilde ayarlanmış olarak alt varlık örneğine ek açıklama ekler: ana varlığın birincil anahtar sütununun adı ve entityColumn üst öğeye referans veren alt varlık sütununun adına ayarlayın varlığa ilişkin bir birincil anahtardır.

Kotlin

data class UserAndLibrary(
    @Embedded val user: User,
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    val library: Library
)

Java

public class UserAndLibrary {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userOwnerId"
    )
    public Library library;
}

Son olarak, DAO sınıfına tüm veri örneklerini döndüren bir yöntem ekleyin üst varlık ile alt varlığı eşleyen sınıfıdır. Bu yöntem için İki sorgu çalıştırmak için oda bulunduğundan, bu alana @Transaction ek açıklamasını ekleyin yöntemini kullanmanızı öneririz.

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersAndLibraries(): List<UserAndLibrary>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserAndLibrary> getUsersAndLibraries();

Bire-çok ilişkileri tanımlama

İki varlık arasındaki bire-çok ilişki, her bir varlığın üst varlığın örneği, alt öğenin sıfır veya daha fazla örneğine karşılık gelir ancak alt varlığın her örneği yalnızca bir taneye karşılık gelebilir örneğidir.

Müzik yayın uygulaması örneğinde, kullanıcının düzenleme yapabildiğini varsayalım şarkılarını oynatma listelerine dönüştürüyor. Her kullanıcı istediği sayıda oynatma listesi oluşturabilir. Ancak her oynatma listesi tam olarak bir kullanıcı tarafından oluşturulur. Dolayısıyla, User varlığı ile Playlist varlığı arasında bire-çok bir ilişki.

Bire-çok bir ilişki tanımlamak için önce iki varlık için bir sınıf oluşturun. Bire bir ilişkide olduğu gibi, alt varlık ana varlığın birincil anahtarına verilen bir referanstır.

Kotlin

@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
)

Java

@Entity
public class User {
    @PrimaryKey public long userId;
    public String name;
    public int age;
}

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

Kullanıcı listesini ve ilişkili oynatma listelerini sorgulamak için önce bu iki varlık arasındaki bire-çok ilişki modelini kullanır. Bunu yapmak için Her örneğin üst varlığın bir örneğini içerdiği yeni bir veri sınıfı ve karşılık gelen tüm alt varlık örneklerinin listesi. @Relation ekleyin parentColumn değeri şu şekilde ayarlanmış olarak alt varlık örneğine ek açıklama ekler: ana varlığın birincil anahtar sütununun adı ve entityColumn üst öğeye referans veren alt varlık sütununun adına ayarlayın varlığa ilişkin bir birincil anahtardır.

Kotlin

data class UserWithPlaylists(
    @Embedded val user: User,
    @Relation(
          parentColumn = "userId",
          entityColumn = "userCreatorId"
    )
    val playlists: List<Playlist>
)

Java

public class UserWithPlaylists {
    @Embedded public User user;
    @Relation(
         parentColumn = "userId",
         entityColumn = "userCreatorId"
    )
    public List<Playlist> playlists;
}

Son olarak, DAO sınıfına tüm veri örneklerini döndüren bir yöntem ekleyin üst varlık ile alt varlığı eşleyen sınıfıdır. Bu yöntem için İki sorgu çalıştırmak için oda bulunduğundan, bu alana @Transaction ek açıklamasını ekleyin yöntemini kullanmanızı öneririz.

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylists(): List<UserWithPlaylists>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylists> getUsersWithPlaylists();

Çoka-çok ilişkileri tanımlama

İki varlık arasındaki çoka-çok ilişki, her bir varlığın üst varlığın örneği, alt öğenin sıfır veya daha fazla örneğine karşılık gelir varlık, tersi de geçerlidir.

Müzik yayın uygulaması örneğinde, kullanıcı tanımlı oynatma listelerindeki şarkıları düşünün. Her şarkı listesinde birçok şarkı bulunabilir ve her şarkı, birçok şarkıya ait olabilir. farklı oynatma listeleri oluşturabilirsiniz. Dolayısıyla, bir çizelgede çoka-çok Playlist varlığı ile Song varlığı arasında geçiş yapın.

Çoka-çok bir ilişki tanımlamak için önce ikisine ait her biri için bir sınıf oluşturun. varlıklarından oluşur. Çoka-çok ilişkiler diğer ilişki türlerinden farklıdır çünkü genellikle alt varlıktaki ana varlığa atıfta bulunmalıdır. Bunun yerine, ilişkisel bir varlığı temsil edecek sınıf veya çapraz referans tablosunda gösterilir. Çapraz referans tablosu, Bu tablodaki çoka-çok ilişkideki her bir varlığın birincil anahtarı yardımcı olabilir. Bu örnekte, çapraz başvuru tablosundaki her bir satır referans verilen Playlist örneği ile Song örneğinin bir eşlemesi referans verilen şarkı listesinde yer alıyor.

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;
}

Sonraki adım, bu ilgili varlıkları nasıl sorgulamak istediğinize bağlıdır.

  • Oynatma listelerini ve bu şarkıya karşılık gelen şarkıların listesini sorgulamak isterseniz her oynatma listesinde tek bir Playlist nesnesi içeren yeni bir veri sınıfı oluşturun ve oynatma listesinde yer alan tüm Song nesnelerinin listesi.
  • Şarkıları ve bu şarkıya karşılık gelen şarkı listelerinin listesini sorgulamak isterseniz Her biri, tek bir Song nesnesi ve bir liste içeren yeni bir veri sınıfı oluşturun Şarkının yer aldığı Playlist nesnelerin tümü

Her iki durumda da associateBy özelliğinin her birindeki @Relation ek açıklamasına bu sınıfları kullanarak ilişkiyi sağlayan çapraz referans varlığını Playlist varlığı ile Song varlığı arasında.

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, sorgu işlevini kullanıma sunmak için DAO sınıfına en iyi uygulamaları paylaşacağım.

  • getPlaylistsWithSongs: Bu yöntem veritabanını sorgular ve sonuçta ortaya çıkan PlaylistWithSongs nesne.
  • getSongsWithPlaylists: Bu yöntem veritabanını sorgular ve sonuçta ortaya çıkan SongWithPlaylists nesne.

Bu yöntemlerin her biri iki sorgu çalıştırmak için Oda gerektirir. Bu nedenle, @Transaction ek açıklamasını her iki yönteme de eklemenizi sağlar. Böylece, İşlem atomik olarak gerçekleştirilir.

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();

İç içe yerleştirilmiş ilişkileri tanımlama

Bazen, hepsi bir arada bulunan üç veya daha fazla tablodan oluşan bir kümeyi sorgulamanız gerekebilir. bir araya getirmektir. Bu durumda, iç içe yerleştirilmiş ilişkileri tanımlarsınız yardımcı olabilir.

Müzik yayın uygulaması örneğinde tüm müziklerinizin kullanıcıları, her kullanıcı için tüm oynatma listelerini ve her oynatma listesindeki tüm şarkıları her kullanıcı için geçerli olur. Kullanıcıların şu reklamverenle bire-çok ilişkisi vardır oynatma listeleri ve oynatma listelerinin çoka-çok ilişkisi vardır. şarkılar. Aşağıdaki kod örneğinde, bu sınıfları temsil eden sınıflar öğe türlerinin yanı sıra çoka-çok ilişkisine ilişkin çapraz referans tablosu da oynatma listeleri ve şarkılar arasında:

Kotlin

@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
)

@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 User {
    @PrimaryKey public long userId;
    public String name;
    public int age;
}

@Entity
public class Playlist {
    @PrimaryKey public long playlistId;
    public long userCreatorId;
    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;
}

İlk olarak, ilk olarak kümenizdeki tablolardan ikisi arasındaki ilişkiyi ve bir veri sınıfı ve @Relation ek açıklaması. İlgili içeriği oluşturmak için kullanılan aşağıdaki örnekte çoka-çok modelleyen bir PlaylistWithSongs sınıfı gösterilmektedir Playlist varlık sınıfı ile Song varlık sınıfı arasındaki ilişki:

Kotlin

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

Java

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

Bu ilişkiyi temsil eden bir veri sınıfı tanımladıktan sonra başka bir veri sınıfı oluşturun ve kümenizdeki başka bir tablo arasındaki ilişkiyi modelleyen veri sınıfı ilk ilişki sınıfı, "iç içe yerleştirme" bu yeni sürecin içindeki mevcut bir. Aşağıdaki örnekte, bir UserWithPlaylistsAndSongs sınıfı gösterilmektedir. User varlık sınıfı ile PlaylistWithSongs ilişki sınıfı:

Kotlin

data class UserWithPlaylistsAndSongs(
    @Embedded val user: User
    @Relation(
        entity = Playlist::class,
        parentColumn = "userId",
        entityColumn = "userCreatorId"
    )
    val playlists: List<PlaylistWithSongs>
)

Java

public class UserWithPlaylistsAndSongs {
    @Embedded public User user;
    @Relation(
        entity = Playlist.class,
        parentColumn = "userId",
        entityColumn = "userCreatorId"
    )
    public List<PlaylistWithSongs> playlists;
}

UserWithPlaylistsAndSongs sınıfı, ilişkileri dolaylı olarak modeller üç varlık sınıfı arasında bulunuyor: User, Playlist ve Song. Bu Şekil 1'de gösterilmiştir.

UserWithOynatmaListeleriAndSongs, Kullanıcı ve
  Oynatma Listesi arasındaki ilişkiyi modeller.
  ve Şarkı.

Şekil 1. Şemadaki ilişki sınıflarının müzik yayın uygulaması örneği.

Grubunuzda daha fazla tablo varsa kalan her tablo ve modelleyen ilişki sınıfı arasındaki ilişki her tür ilişkiyi ele alalım. Bu yöntem, bir iç içe yerleştirilmiş bir zincir tablolar arasında ilişki kurmak için de kullanabilirsiniz.

Son olarak, dönüşüm gerçekleştiren sorgu işlevini kullanıma sunmak için DAO sınıfına en iyi uygulamaları paylaşacağız. Bu yöntemde birden fazla sorgu çalıştırmak için Oda gerekir. Bu nedenle, @Transaction ek açıklaması Böylece tüm işlem atomik olarak gerçekleşsin:

Kotlin

@Transaction
@Query("SELECT * FROM User")
fun getUsersWithPlaylistsAndSongs(): List<UserWithPlaylistsAndSongs>

Java

@Transaction
@Query("SELECT * FROM User")
public List<UserWithPlaylistsAndSongs> getUsersWithPlaylistsAndSongs();

Ek kaynaklar

Odadaki öğeler arasındaki ilişkileri tanımlama hakkında daha fazla bilgi edinmek için ek kaynakları inceleyin.

Örnekler

Videolar

Bloglar