【问题标题】:How to insert a "one to one" room database如何插入“一对一”房间数据库
【发布时间】:2021-07-31 18:54:23
【问题描述】:

我正在尝试在 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)
         
        }

repository 和 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。

【问题讨论】:

    标签: android android-room


    【解决方案1】:

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

    考虑以下使用您的类(用户、库和 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)

    结合上述活动中的代码(为了方便和简洁,在主线程上运行):-

        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
    
    • 即一切都如预期的那样。

    【讨论】:

      【解决方案2】:

      这工作得很好,但我必须承认这不是那么用户友好,也没有从谷歌的任何地方记录下来。批评者是针对谷歌而不是你。 是否可以做这样的事情(c#和实体框架示例)

      var dept = new Department()
      {
          Name = "Admin"
      };
       
      var emp = new Employee()
      {
          Name = "Matt",
          Designation = "Head",
          Department = dept
      };
       
      using (var context = new CompanyContext())
      {
          context.Add(emp);
          await context.SaveChangesAsync();
      }
      

      这将是使用框架库的一种非常直观的方式

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-19
        • 2019-04-17
        • 1970-01-01
        • 2023-01-12
        • 2021-07-04
        • 2020-06-13
        • 2018-06-13
        • 1970-01-01
        相关资源
        最近更新 更多