android - 如何插入 "one to one"房间数据库

标签 android android-room

我正在尝试在 android 中插入一个具有一对一关系的对象。 更准确地说,我正在尝试遵循以下示例 googles official documentation

我正在使用两个类“用户”和“库”。 我遇到的问题是如何将元素插入数据库中。 我的代码是这样写的

  @Entity
data class Library(
    @PrimaryKey(autoGenerate = true) val libraryId: Long = 0,
    val userOwnerId: Long
)


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

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

插入的逻辑如下所示

private val repository = UserRepository(application)

    fun insertUser() {
        val user1 = User(name = "User1", age = 31)
        val user2 = User(name = "User2", age = 32)
        val library1 = Library(userOwnerId = user1.userId)
        val library2 = Library(userOwnerId = user2.userId)

        viewModelScope.launch {
            repository.insertUser(user1)
            
            repository.insertUser(user2)
            
            repository.insertLibrary(library1)
            
            repository.insertLibrary(library2)
         
        }

存储库和 dao 类的代码如下所示

//repository
suspend fun insertUser(user: User) = appDataBase.userDao().insertUser(user)

suspend fun insertLibrary(library: Library)=appDataBase.userDao().insertLibrary(library)

//dao
@Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertLibrary(library: Library)

问题在于库表中的外键始终为0。

最佳答案

我认为您的问题是由于您插入库数据的方式造成的。更具体地说,当您插入库时,您是否设置库userOwnerId的值? (我相信不是或者正在将其设置为 0)。

考虑以下内容,根据问题使用您的类(User、Library 和 userAndLibrary),并使用以下 @Dao 和相当标准的 @Database :-

@Dao
abstract class AllDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(library: Library): Long
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(user: User): Long
    @Query("SELECT * FROM user")
    abstract fun getAllUsers(): List<User>
    @Query("SELECT * FROM library")
    abstract fun getAllLibraries(): List<Library>
    @Query("SELECT * FROM user")
    abstract fun getUsersAndThierLibrary(): List<UserAndLibrary>
}
  • 注意插入返回Long(即插入行的id)

结合上面的 Activity 中的代码(为了方便和简洁而在主线程上运行):-

    db = TheDatabase.getInstance(this)
    dao = db.getAllDao()

    /* Explanatory Insert */
    var firstUser = User(name = "Susan",age = 20)
    var firstUserId = dao.insert(firstUser)
    dao.insert(Library(userOwnerId = firstUserId))

    /* More Concise Inserts */
    dao.insert(Library(userOwnerId = dao.insert(User(name ="Fred",age = 21))))
    dao.insert(Library(userOwnerId = dao.insert(User(name ="Mary",age= 19))))

    for (u: User in dao.getAllUsers()) {
        Log.d(TAG," User is ${u.name} ID is ${u.userId} age is ${u.age}")
    }
    for (l: Library in dao.getAllLibraries()) {
        Log.d(TAG,"Library is ${l.libraryId} owned by ${l.userOwnerId}")
    }
    for(ual: UserAndLibrary in dao.getUsersAndThierLibrary()) {
        Log.d(TAG,"User = ${ual.user.name} Library ID is ${ual.library.libraryId}")
    }
  • 再次注意插入用户时使用返回的值(userId)。

可以看出上面插入了 3 个用户和库。然后它提取所有用户、所有库和 UserAndLibrary。结果是:-

2021-07-31 12:29:41.888 D/MYINFO:  User is Susan ID is 1 age is 20
2021-07-31 12:29:41.889 D/MYINFO:  User is Fred ID is 2 age is 21
2021-07-31 12:29:41.889 D/MYINFO:  User is Mary ID is 3 age is 19
2021-07-31 12:29:41.890 D/MYINFO: Library is 1 owned by 1
2021-07-31 12:29:41.890 D/MYINFO: Library is 2 owned by 2
2021-07-31 12:29:41.890 D/MYINFO: Library is 3 owned by 3
2021-07-31 12:29:41.894 D/MYINFO: User = Susan Library ID is 1
2021-07-31 12:29:41.895 D/MYINFO: User = Fred Library ID is 2
2021-07-31 12:29:41.895 D/MYINFO: User = Mary Library ID is 3
  • 即一切都如预期。

关于android - 如何插入 "one to one"房间数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68598208/

相关文章:

Android Room 插入重复实体

compiler-errors - 带有 RxJava Single<List<T>> 编译错误的 Android Room

java - 将Amazon SimpleDB与Android结合使用

android - JodaTime - 如何将 ISO 8601 时间字符串解析为 DateTime?

java - Listview onclick 中的 TextView 冲突

java - 如何将 bundle 数据从一个 fragment 获取到另一个 fragment ?

android - 如何在有空间的情况下执行繁重的数据库操作?

java - Android 客户端和 Windows 服务器之间的 TCP 连接在随机时间后中断

android - 如何创建与 Room 一起使用的 sqlite View ?

android - Room 的 JavaDoc 在哪里?