【问题标题】:Kotlin: How to insert a list of objects into Room?Kotlin:如何将对象列表插入到 Room 中?
【发布时间】:2018-06-19 01:33:49
【问题描述】:

我正在尝试在基本接口中定义常见的CRUD 方法,如下所示:

interface BaseDao<in I> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun create(obj: I)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun createAll(objects: List<I>)

    @Delete
    fun delete(obj: I)

}

Room 的以下ProductDao 接口继承自基本接口:

@Dao
interface ProductDao : BaseDao<Product> {

    // Specific methods

}

当我编译fun createAll(objects: List&lt;I&gt;) 的定义时会产生以下错误:

参数的类型必须是带有@Entity注解的类或其集合/数组。

【问题讨论】:

  • 您的 Product 表是否使用实体注释进行了注释?
  • 就是盒子上写的——I需要标注@Entity
  • 基类中定义的所有其他方法都有效。只有createAll() 方法不起作用。
  • 不,“I”不需要注解,但如果您确实将 BaseDao 设为带有@Dao 注解的抽象类,它将起作用

标签: android kotlin android-room


【解决方案1】:

尝试将@JvmSuppressWildcards 添加到您的函数中。

@Insert
@JvmSuppressWildcards
fun createAll(objects: List<I>)

来自文档:

指示编译器生成或省略类型参数的通配符,这些类型参数对应于具有声明站点差异的参数,例如 Collection has。

仅当声明似乎不方便从 Java 中使用时才可能有用。

【讨论】:

    【解决方案2】:

    我已通过以下方式解决问题:

    @Dao
    interface BaseDao<T> {
    
        /**
         * Insert a list in the database. If the item already exists, replace it.
         *
         * @param list the items to be inserted.
         */
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        @JvmSuppressWildcards
        abstract fun insertAll(list: List<T>)
    
    }
    

    @JvmSuppressWildcards帮我解决了问题

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,我相信我找到了解决方案:

      Kotlin 不可能创建泛型对象数组,因此您必须做出这样的解决方法:

      @Insert(onConflict = OnConflictStrategy.REPLACE)
      fun create(obj: I)
      
      @Transaction
      fun createAll(objects: List<I>) = objects.forEach {insert(it)}
      

      @Transaction 应该让这一切发生在一个事务中,因此它不应该引入任何性能问题,但我不确定这一点。

      还有一个简单的:

      @Insert(onConflict = OnConflictStrategy.REPLACE)
      fun createAll(objects: List<Product>)
      

      只要它使用的是真实对象而不是泛型,它也可以工作。

      【讨论】:

        【解决方案4】:

        你应该为你的模型类添加@Entity注解(你应该为Dao方法添加具体的模型类), 但是您在界面BaseDao&lt;in I&gt; 中使用泛型。 https://developer.android.com/training/data-storage/room/defining-data.html

        【讨论】:

          【解决方案5】:

          我的解决方法是在 Java 中实现 BaseDao 接口,直到问题仍然存在。

          public interface IBaseDao<T> {
          
              @Insert(onConflict = OnConflictStrategy.REPLACE)
              @WorkerThread
              void save(T item);
          
              @Delete
              @WorkerThread
              void delete(T item);
          
              @Delete
              @WorkerThread
              void deleteAll(List<T> items);
          
              @Insert(onConflict = OnConflictStrategy.REPLACE)
              @WorkerThread
              void saveAll(List<T> items);
          }
          

          Kotlin 中的抽象 BaseDao

          abstract class BaseDao<T> : IBaseDao<T> {
          
              @WorkerThread
              open fun getAll(): List<T> = TODO("Override and place the annotation @Query. Ex: @Query(\"SELECT * FROM Model\")")
          
              @WorkerThread
              open fun loadAll(): LiveData<List<T>> = TODO("Override and place the annotation @Query. Ex: @Query(\"SELECT * FROM Model\")")
          }
          

          有效!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-22
            • 2023-03-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-02-04
            相关资源
            最近更新 更多