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

21

我正在尝试定义一个基本接口中的常见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)

}

下面的 ProductDao 接口是基于以下基础接口的 Room 接口:

@Dao
interface ProductDao : BaseDao<Product> {

    // Specific methods

}

当我编译 fun createAll(objects: List<I>)的定义时,出现以下错误:

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


你的Product表是否使用了Entity注解进行标注? - arubin
1
必须在I上用@Entity进行注释——这就是盒子上写的内容。 - Abhijit Sarkar
1
在基类中定义的所有其他方法都有效。只有 createAll() 方法无法正常工作。 - JJD
1
不需要对"I"进行注释,但如果您使用@Dao注释将BaseDao作为抽象类,则它将起作用。 - arubin
5个回答

12

尝试在您的函数中添加@JvmSuppressWildcards

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

来自文档:

指示编译器为具有声明点变异的参数对应的类型参数生成或省略通配符,例如 Collection。

仅当从Java使用声明似乎不方便时,它可能有所帮助。


10

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

@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 对我很有帮助


2

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

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>)

只要使用真实对象而不是泛型,这段代码也可以正常工作。

0
我的解决方法是在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\")")
}

它运行正常!


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接