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<I>)
的定义时会产生以下错误:
参数的类型必须是带有@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<in I>
中使用泛型。
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 中?的主要内容,如果未能解决你的问题,请参考以下文章
kotlin 升级到 1.6.0 后如何在 Room Dao 中使用挂起修饰符?