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 teknik gerekçesi hakkında bilgi edinmek için Room'un nesne referanslarına neden izin vermediğini anlama başlıklı makaleyi inceleyin.
İlişki türleri
Oda, aşağıdaki ilişki türlerini destekler:
- Bire bir: Tek bir öğenin başka bir tek öğeyle ilişkili olduğu bir ilişkiyi temsil eder.
- Bire-çok: Tek bir öğenin başka türden birden fazla öğeyle ilişkili olabileceği bir ilişkiyi temsil eder.
- Çoklu-çoklu: Bir türden birden fazla öğenin başka bir türden birden fazla öğeyle ilişkilendirilebileceği bir ilişkiyi temsil eder. Bu işlem genellikle bir birleştirme tablosu gerektirir.
- İç içe yerleştirilmiş ilişkiler (yerleştirilmiş nesneler kullanılır): Bir öğenin alan olarak başka bir öğeyi içerdiği ve bu iç içe yerleştirilmiş öğenin başka öğeler içerebileceği bir ilişkiyi temsil eder. Bu,
@Embedded
ek açıklamasını kullanır.
İki yaklaşım arasından seçim yapma
Room'da, varlıklar arasındaki ilişkiyi tanımlamanın ve sorgulamanın iki yolu vardır. Aşağıdakilerden birini kullanabilirsiniz:
- Yerleşik nesneleri olan bir ara veri sınıfı veya
- Çok harita döndürme türüne sahip bir ilişkisel sorgu yöntemi.
Ara veri sınıflarını kullanmaya yönelik belirli bir nedeniniz yoksa çok harita döndürme 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ı yazmanızı önler ancak ek veri sınıfları gerektirdiğinden kod karmaşıklığının artmasına da neden olabilir. Özetle, çok harita döndürme türü yaklaşımı SQL sorgularınızın daha fazla çalışma yapmasını, ara veri sınıfı yaklaşımı ise kodunuzun daha fazla çalışma yapmasını gerektirir.
Ara veri sınıfı yaklaşımını kullanma
Ara veri sınıfı yaklaşımında, Room varlıkları 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şlemeleri yerleşik 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ış kitaplık kullanıcılarını temsil etmek için bir UserBook
veri sınıfı ve veritabanından UserBook
örnekleri 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 harita döndürme türü yaklaşımını kullanma
Çok harita döndürme 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 bir çoklu harita döndürme türü tanımlar ve öğeleriniz 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şik nesne oluşturma
Bazen, nesne birkaç alan içerse bile veritabanı mantığınızda bir öğeyi veya veri nesnesini uyumlu bir bütün olarak ifade etmek istersiniz. Bu durumlarda, bir tablodaki alt alanlarına ayırmak istediğiniz bir nesneyi temsil etmek için @Embedded
ek açıklamasını kullanabilirsiniz. Ardından, diğer sütunlarda olduğu gibi yerleşik alanları sorgulayabilirsiniz.
Örneğin, User
sınıfınız street
, city
, state
ve postCode
adlı alanların bir bileşimini temsil eden Address
türündeki bir alan içerebilir. Oluşturulan sütunları tabloda ayrı olarak depolamak için bir Address
alanı ekleyin. Bu, @Embedded
ile ek açıklama yapılan User
sınıfında görünür. Aşağıdaki kod snippet'inde bu 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 tablo, şu adlara sahip sütunlar içerir: id
, firstName
, street
, state
, city
ve post_code
.
Bir öğenin aynı türde birden fazla yerleşik alanı varsa prefix
özelliğini ayarlayarak her sütunu benzersiz tutabilirsiniz. Ardından Room, sağlanan değeri yerleşik nesnenin 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 kaynakları inceleyin.
Videolar
- Room'daki Yenilikler (Android Dev Summit 2019)