web-dev-qa-db-ja.com

Kotlin:オブジェクトのリストをRoomに挿入する方法は?

以下に示すように、基本インターフェイスで共通の [〜#〜] 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で注釈が付けられたクラスまたはそのコレクション/配列である必要があります。

10
JJD

関数に@JvmSuppressWildcardsを追加してみてください。

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

ドキュメントから:

たとえばCollectionのように、宣言サイトに差異があるパラメーターに対応する型引数のワイルドカードを生成または省略するようにコンパイラーに指示します。

宣言がJavaからの使用に不便であると思われる場合にのみ役立つ場合があります。

6
nsc9012

次の方法で問題を解決しました:

@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(kist: List<T>)

}

@ JvmSuppressWildcards私のためにトリックを行いました

1
Waqar UlHaq

追加する必要があります@Entityモデルクラスの注釈(Daoメソッドには具体的なモデルクラスが必要です)ですが、インターフェースでジェネリックを使用しますBaseDao<in I>https://developer.Android.com/training/data-storage/room/defining-data.html

0
p.alexey

私の修正は、問題が解決するまでJavaBaseDaoインターフェイスを実装することでした。

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
Fredy Mederos

私は同じ問題を抱えていて、解決策を見つけたと思います:

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