Bibliothèque de persistance de la chambre. Tout supprimer


182

Comment puis-je supprimer toutes les entrées d'une table spécifique à l'aide de la bibliothèque de persistance de pièce? Je dois supprimer la table, mais je ne trouve aucune information sur la façon de procéder.

Uniquement lors de la migration de la base de données ou pour charger toutes les entrées et les supprimer :)


14
Depuis la salle 1.1.0, vous pouvez utiliser clearAllTables()qui "supprime toutes les lignes de toutes les tables qui sont enregistrées dans cette base de données en tant qu'entités ()." J'ai inclus cela comme réponse ci-dessous, mais je reproduis ici pour plus de visibilité.
Dick Lucas

Réponses:


446

Vous pouvez créer une méthode DAO pour ce faire.

@Dao 
interface MyDao {
    @Query("DELETE FROM myTableName")
    public void nukeTable();
}

3
Ah, je n'y avais pas pensé. J'ai supposé que @Queryc'était limité aux choses qui retournent des ensembles de résultats (semblables à rawQuery()). Très cool!
CommonsWare

1
@yigit puis-je demander qui @Deletene prend aucun paramètre et tout supprimer de la table? J'essaye de trouver le tracker de Room pour classer ça ...
Felipe Duarte

4
Fais attention! quant à la version room alpha4, cette technique entraînera un échec de compilation gradle
yshahak

2
Et pourquoi pas Ids? J'ai aimé cela, mais les identifiants de table continuent d'augmenter. Dans une table réelle, les identifiants de suppression sont également supprimés pour recommencer à zéro.
Ioane Sharvadze

6
@yigit Existe-t-il un moyen de savoir si la requête s'est exécutée avec succès ou s'il y a eu une erreur?
Aditya Ladwa

107

Depuis Room, 1.1.0vous pouvez utiliser clearAllTables () qui:

Supprime toutes les lignes de toutes les tables enregistrées dans cette base de données en tant qu'entités ().


44
Attention: clearAllTables () est asynchrone et il n'y a aucun moyen de savoir quand il se termine.
Alexey

2
@Alexey mais pourrait-il y avoir des problèmes pour essayer de sauvegarder quelque chose après clearAllTables? Comme dans, essaiera-t-il seulement d'insérer APRÈS la compensation? Parce que je suis d'accord avec ça.
FirstOne

2
@FirstOne clearAllTables démarre simplement une transaction sur un nouveau thread d'arrière-plan. Il supprime toutes les données des tables, puis valide cette transaction. Si vous démarrez votre transaction plus tard que clearAllTables commence son, tout va bien. Cela étant dit, si vous essayez d'insérer des données juste après avoir appelé clearAllTable, votre insertion peut commencer avant que clearAllTable ne commence la transaction et vous perdrez toutes vos données. Si vous devez insérer de nouvelles données juste après avoir appelé clearAllTable, ajoutez au moins un délai.
Alexey

2
@Alexey Existe-t-il un moyen d'utiliser une méthode de rappel ou similaire pour déterminer l'état de la transaction de suppression? En d'autres termes, si l'état de la transaction de suppression est terminé, continuez avec la méthode d'insertion de données.
AJW

1
@AJW Non, pour le moment, il n'y a toujours aucun moyen de savoir quand l'opération est terminée. Si vous avez vraiment besoin de cette fonctionnalité, vous voudrez peut-être essayer quelque chose comme SELECT name FROM sqlite_master WHERE type='table'puis manuellement DELETE FROM {TABLE}. Je n'ai pas testé cela cependant.
Alexey le

33

Si vous souhaitez supprimer une entrée du tableau dans la salle, appelez simplement cette fonction,

@Dao
public interface myDao{
    @Delete
    void delete(MyModel model);
}

Mise à jour: Et si vous souhaitez supprimer le tableau complet, appelez la fonction ci-dessous,

  @Query("DELETE FROM MyModel")
  void delete();

Remarque: Ici, MyModel est un nom de table.


J'ai eu cette erreur après avoir utilisé votre erreur de code de mise à jour: Une méthode DAO abstraite doit être annotée avec une et une seule des annotations suivantes: Insertion, Suppression, Requête, Mise à jour, RawQuery void delete ();
bramastaVic

12

Utilisez clearAllTables () avec RXJava comme ci-dessous pour éviterjava.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

Completable.fromAction(new Action() {
        @Override
        public void run() throws Exception {
            getRoomDatabase().clearAllTables();
        }
    }).subscribeOn(getSchedulerProvider().io())
            .observeOn(getSchedulerProvider().ui())
            .subscribe(new Action() {
                @Override
                public void run() throws Exception {
                    Log.d(TAG, "--- clearAllTables(): run() ---");
                    getInteractor().setUserAsLoggedOut();
                    getMvpView().openLoginActivity();
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.d(TAG, "--- clearAllTables(): accept(Throwable throwable) ----");
                    Log.d(TAG, "throwable.getMessage(): "+throwable.getMessage());


                }
            });

4

J'ai eu des problèmes avec la méthode de suppression de toutes les méthodes lors de l'utilisation de RxJava pour exécuter cette tâche en arrière-plan. Voici comment je l'ai finalement résolu:

@Dao
interface UserDao {
    @Query("DELETE FROM User")
    fun deleteAll()
}

et

fun deleteAllUsers() {
    return Maybe.fromAction(userDao::deleteAll)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe ({
            d("database rows cleared: $it")
        }, {
            e(it)
        }).addTo(compositeDisposable)
}

5
Lorsque vous utilisez Kotlin, vous pouvez simplement l'envelopper au thread {}lieu de le futzing avec RxJava
Erik

1

En combinant ce que dit Dick Lucas et en ajoutant une réinitialisation auto-incrémentielle à partir d'autres publications StackOverFlow, je pense que cela peut fonctionner:

    fun clearAndResetAllTables(): Boolean {
        val db = db ?: return false

        // reset all auto-incrementalValues
        val query = SimpleSQLiteQuery("DELETE FROM sqlite_sequence")

        db.beginTransaction()
        return try {
            db.clearAllTables()
            db.query(query)
            db.setTransactionSuccessful()
            true
        } catch (e: Exception){
            false
        } finally {
            db.endTransaction()
        }
    }

Pour ce que ça vaut, j'ai trouvé qu'il était plus facile de le faire via context.deleteDatabase («nom»), puis de simplement réinstituer et repeupler la base de données via Room.databaseBuilder (). AddCallback lors du premier accès.
Bink

Qu'est-ce que sqlite_sequence?
RoyalGriffin

0

Pour utiliser la salle sans abuser de l' @Queryannotation, utilisez d'abord @Querypour sélectionner toutes les lignes et les mettre dans une liste, par exemple:

@Query("SELECT * FROM your_class_table")

List`<`your_class`>` load_all_your_class();

Mettez sa liste dans l'annotation de suppression, par exemple:

@Delete

void deleteAllOfYourTable(List`<`your_class`>` your_class_list);

0

Voici comment je l'ai fait à Kotlin.

  1. Injectez room db dans l'activité en utilisant DI (Koin).

     private val appDB: AppDB by inject()
  2. Ensuite, vous pouvez simplement appeler clearAllTables ()

    plaisir privé clearRoomDB () {GlobalScope.launch {appDB.clearAllTables () preferences.put (PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false) preferences.put (PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO_DB, false)}}

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.