Kotlin:如何将对象列表插入到 Room 中?

Posted

技术标签:

【中文标题】Kotlin:如何将对象列表插入到 Room 中?【英文标题】:Kotlin: How to insert a list of objects into 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 注解的抽象类,它将起作用 【参考方案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\")")

有效!

【讨论】:

以上是关于Kotlin:如何将对象列表插入到 Room 中?的主要内容,如果未能解决你的问题,请参考以下文章

上手使用 Room Kotlin API

如何构建和查询 Room DB 以返回多个类的对象列表?

kotlin 升级到 1.6.0 后如何在 Room Dao 中使用挂起修饰符?

如何使用带有 Kotlin 的 Room 和 moshi 持久化带有 JSON 数组的 JSON 对象

链接多个调用 RxJava、Room 和 Retrofit

Room - 插入新值后执行删除