SQLite ilişkisel bir veritabanı olduğundan, varlıklar arasındaki ilişkileri tanımlayabilirsiniz. Ancak çoğu nesne-ilişkisel eşleme kitaplığı, varlık nesnelerinin birbirine referans vermesine izin verirken Room bunu açıkça yasaklar. Bu kararın arkasındaki teknik gerekçeyi öğrenmek için Room'un neden nesne referanslarına izin vermediğini anlama başlıklı makaleyi inceleyin.
İlişki türleri
Room aşağıdaki ilişki türlerini destekler:
- Bire bir: Tek bir varlığın başka bir tek varlıkla ilişkili olduğu durumu ifade eder.
- Bire-çok: Tek bir varlığın başka bir türden birden fazla varlıkla ilişkili olabileceği bir ilişkiyi temsil eder.
- Çoktan çoka: Bir türdeki birden fazla öğenin başka bir türdeki birden fazla öğeyle ilişkili olabileceği bir ilişkiyi ifade eder. Bu genellikle bir birleşim tablosu gerektirir.
- İç İçe İlişkiler (yerleştirilmiş nesneler kullanılarak): Bir öğenin başka bir öğeyi alan olarak içerdiği ve bu iç içe öğenin başka öğeler de içerebildiği bir ilişkiyi ifade eder. Bu,
@Embeddednotunu kullanır.
İki yaklaşım arasından seçim yapın
Room'da, öğeler arasındaki ilişkiyi tanımlamanın ve sorgulamanın iki yolu vardır. Şunlardan birini kullanabilirsiniz:
- Yerleştirilmiş nesneler içeren bir ara veri sınıfı veya
- Çoklu harita dönüş türüne sahip ilişkisel bir sorgu yöntemi.
Ara veri sınıflarını kullanmak için belirli bir nedeniniz yoksa çoklu harita dönüş türü yaklaşımını kullanmanızı öneririz. Bu yaklaşım hakkında daha fazla bilgi edinmek için Çoklu harita döndürme başlıklı makaleyi inceleyin.
Ara veri sınıfı yaklaşımı, karmaşık SQL sorguları yazmaktan kaçınmanızı sağlar ancak ek veri sınıfları gerektirdiğinden kod karmaşıklığının artmasına da neden olabilir. Kısacası, çoklu harita dönüş türü yaklaşımı, SQL sorgularınızın daha fazla iş yapmasını gerektirir. Ara veri sınıfı yaklaşımı ise kodunuzun daha fazla iş yapmasını gerektirir.
Ara veri sınıfı yaklaşımını kullanma
Ara veri sınıfı yaklaşımında, Room varlıklarınız arasındaki ilişkiyi modelleyen bir veri sınıfı tanımlarsınız. Bu veri sınıfı, bir öğenin örnekleri ile başka bir öğenin örnekleri arasındaki eşleşmeleri yerleştirilmiş nesneler olarak tutar. Sorgu yöntemleriniz daha sonra uygulamanızda kullanılmak üzere bu veri sınıfının örneklerini döndürebilir.
Örneğin, belirli kitapları ödünç almış kütüphane kullanıcılarını temsil etmek için bir UserBook veri sınıfı tanımlayabilir ve veritabanından UserBook örneklerinin listesini almak için bir sorgu yöntemi tanımlayabilirsiniz:
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;
}
Çok haritalı dönüş türleri yaklaşımını kullanma
Çoklu harita dönüş türü yaklaşımında, ek veri sınıfları tanımlamanız gerekmez. Bunun yerine, istediğiniz harita yapısına göre yönteminiz için multimap dönüş türünü tanımlar ve varlıklarınız arasındaki ilişkiyi doğrudan SQL sorgunuzda tanımlarsınız.
Örneğin, aşağıdaki sorgu yöntemi, belirli kitapları ödünç almış kütüphane kullanıcılarını temsil etmek için User ve Book örneklerinin eşlemesini döndürür:
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();
Yerleştirilmiş nesneler oluşturma
Bazen, bir nesne birden fazla alan içerse bile veritabanı mantığınızda bir öğeyi veya veri nesnesini tutarlı bir bütün olarak ifade etmek isteyebilirsiniz. Bu durumlarda, bir tabloda alt alanlarına ayırmak istediğiniz bir nesneyi temsil etmek için @Embedded ek açıklamasını kullanabilirsiniz. Daha sonra, diğer tek tek sütunlarda olduğu gibi yerleştirilmiş alanları sorgulayabilirsiniz.
Örneğin, User sınıfınız street, city, state ve postCode adlı alanların bileşimini temsil eden Address türünde bir alan içerebilir. Oluşturulan sütunları tabloda ayrı ayrı depolamak için bir Address alanı ekleyin. Bu, @Embedded ile açıklama eklenmiş User sınıfında görünmelidir. Aşağıdaki kod snippet'inde bu durum 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;
}
User nesnesini temsil eden tabloda şu adlara sahip sütunlar bulunur: id, firstName, street, state, city ve post_code.
Bir öğede aynı türden birden fazla yerleştirilmiş alan varsa prefix özelliğini ayarlayarak her sütunu benzersiz tutabilirsiniz. Ardından Room, sağlanan değeri yerleştirilmiş nesnedeki her sütun adının başına ekler.
Ek kaynaklar
Room'da öğeler arasındaki ilişkileri tanımlama hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara göz atın.
Videolar
- Room'daki Yenilikler (Android Dev Summit 2019)