web-dev-qa-db-fra.com

Kotlin: Comment insérer une liste d'objets dans Room?

J'essaie de définir les méthodes CRUD communes dans une interface de base, comme indiqué ici:

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)

}

L'interface ProductDao suivante pour Room hérite de l'interface de base:

@Dao
interface ProductDao : BaseDao<Product> {

    // Specific methods

}

Lorsque je compile la définition de fun createAll(objects: List<I>), l'erreur suivante est générée:

Le type du paramètre doit être une classe annotée avec @Entity ou une collection/tableau de celle-ci.

5
JJD

Essayez d’ajouter @JvmSuppressWildcards à votre fonction.

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

De la docs:

Ordonne au compilateur de générer ou d'omettre les caractères génériques pour les arguments de type correspondant aux paramètres avec variance de site de déclaration, par exemple, comme Collection a.

Cela peut être utile seulement si la déclaration semble être peu pratique à utiliser depuis Java.

5
asc-dev

J'ai résolu le problème en:

@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 fait le tour pour moi

1
Waqar UlHaq

Vous devez ajouter l'annotation @Entity pour votre classe de modèle (vous devez avoir une classe de modèle concrète pour les méthodes Dao), , Mais vous utilisez des génériques dans votre interface BaseDao<in I>. https://developer.Android.com/training/ data-storage/room/define-data.html

0
p.alexey

Mon correctif consistait à implémenter l'interface BaseDao dans Java jusqu'à ce que le problème persiste.

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

Résumé BaseDao in Kotlin

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\")")
}

Ça marche!

0
Fredy Mederos

J'ai eu le même problème et je pense avoir trouvé la solution:

Il est impossible pour Kotlin de créer un tableau d'objets génériques. Vous devez donc créer une solution de contournement:

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

@Transaction
fun createAll(objects: List<I>) = objects.forEach {insert(it)}

@Transaction devrait permettre que tout se produise en une seule transaction. Par conséquent, il ne devrait présenter aucun problème de performances, mais je n'en suis pas certain.

De plus, un simple:

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

fonctionnera aussi bien, tant qu’il utilisera des objets réels, pas des génériques.

0
Michał Powłoka