Biblioteka utrzymywania pokoju. Usuń wszystko


181

Jak mogę usunąć wszystkie wpisy z określonej tabeli za pomocą biblioteki utrwalania pokoju? Muszę upuścić tabelę, ale nie mogę znaleźć żadnych informacji, jak to zrobić.

Tylko wtedy, gdy baza danych migruje lub ładuje wszystkie wpisy i usuwa je :)


14
Począwszy od Pokoju 1.1.0, można użyć opcji, clearAllTables()która „usuwa wszystkie wiersze ze wszystkich tabel zarejestrowanych w tej bazie danych jako encje ()”. Zamieściłem to jako odpowiedź poniżej, ale odtwarzam tutaj dla widoczności.
Dick Lucas,

Odpowiedzi:


445

Aby to zrobić, możesz utworzyć metodę DAO.

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

3
Ach, nie myślałem o tym. Zakładałem, że @Querybyło to ograniczone do rzeczy, które zwracają zestawy wyników (podobne do rawQuery()). Bardzo fajny!
CommonsWare

1
@yigit czy mogę zażądać, aby @Deletenie pobierał parametrów i usunąć wszystko z tabeli? Usiłuję znaleźć moduł śledzący Rooma, który go zarejestruje ...
Felipe Duarte,

4
Uważaj! tak jak w przypadku wersji alpha4, ta technika doprowadzi do niepowodzenia kompilacji stopni
yshahak

1
Jak o Ids? Podobało mi się to, ale identyfikatory tabeli nadal rosną. W prawdziwym upuszczaniu tabeli identyfikatory są również upuszczane, aby ponownie zacząć od zera.
Ioane Sharvadze

6
@yigit Czy istnieje sposób, aby dowiedzieć się, czy zapytanie zakończyło się pomyślnie lub czy wystąpił błąd?
Aditya Ladwa,

107

Od Room 1.1.0możesz używać clearAllTables (), które:

Usuwa wszystkie wiersze ze wszystkich tabel zarejestrowanych w tej bazie danych jako podmioty ().


44
Zachowaj ostrożność: clearAllTables () jest asynchroniczny i nie ma sposobu, aby powiedzieć, kiedy się zakończy.
Alexey,

2
@Alexey, ale czy może wystąpić problem z zapisaniem czegoś po clearAllTables? Czy w takim przypadku będzie próbował wstawić PO TYM wyczyszczeniu? Ponieważ nic mi nie jest.
FirstOne

2
@FirstOne clearAllTables po prostu rozpoczyna transakcję na nowym wątku w tle. Usuwa wszystkie dane z tabel, a następnie zatwierdza tę transakcję. Jeśli rozpoczniesz transakcję później niż rozpocznie się clearAllTables, nic ci nie będzie. Biorąc to pod uwagę, jeśli spróbujesz wstawić jakieś dane zaraz po wywołaniu clearAllTable, wstawianie może rozpocząć się przed rozpoczęciem transakcji clearAllTable, a stracisz wszystkie swoje dane. Jeśli musisz wstawić nowe dane zaraz po wywołaniu clearAllTable, dodaj przynajmniej trochę opóźnienia.
Alexey

2
@Alexey Czy istnieje sposób na użycie metody wywołania zwrotnego lub podobnej metody w celu ustalenia stanu transakcji usuwania? Innymi słowy, jeśli stan usuwania transakcji jest zakończony, przejdź do metody wstawiania danych.
AJW

1
@AJW Nie, na razie nie ma możliwości określenia, kiedy operacja jest zakończona. Jeśli naprawdę potrzebujesz tej funkcji, możesz spróbować czegoś takiego, SELECT name FROM sqlite_master WHERE type='table'a następnie ręcznie DELETE FROM {TABLE}. Nie przetestowałem tego jednak.
Alexey

33

Jeśli chcesz usunąć wpis z tabeli w pokoju, po prostu wywołaj tę funkcję,

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

Aktualizacja: jeśli chcesz usunąć całą tabelę, wywołaj funkcję poniżej,

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

Uwaga: Tutaj MyModel jest nazwą tabeli.


dostałem ten błąd po użyciu błędu kodu aktualizacji: abstrakcyjna metoda DAO musi być opatrzona adnotacjami z jedną i tylko jedną z następujących adnotacji: Wstaw, Usuń, Zapytanie, Aktualizacja, RawQuery void delete ();
bramastaVic

12

Użyj clearAllTables () z RXJava, jak poniżej, aby uniknąćjava.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

Miałem problemy z usunięciem wszystkich metod podczas korzystania z RxJava do wykonania tego zadania w tle. Oto jak w końcu to rozwiązałem:

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

i

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

5
Kiedy używasz Kotlina, możesz po prostu owinąć go thread {}zamiast kupować za pomocą RxJava
Erik,

1

Łącząc to, co mówi Dick Lucas i dodając reset autoincremental z innych postów StackOverFlow, myślę, że to może działać:

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

Dla tego, co jest warte, najłatwiej jest to zrobić za pomocą kontekstu.deleteDatabase („nazwa”), a następnie po prostu przywracając i ponownie wypełniając bazę danych za pomocą Room.databaseBuilder (). AddCallback przy pierwszym dostępie.
Bink

Co to jest sqlite_sequence?
RoyalGriffin

0

Aby skorzystać z Pokoju bez nadużywania @Queryadnotacji, najpierw @Querywybierz wszystkie wiersze i umieść je na liście, na przykład:

@Query("SELECT * FROM your_class_table")

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

Umieść swoją listę w adnotacji usuwania, na przykład:

@Delete

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

0

Oto jak to zrobiłem w Kotlinie.

  1. Wstrzyknij db pokoju w aktywności za pomocą DI (Koin).

     private val appDB: AppDB by inject()
  2. Następnie możesz po prostu wywołać clearAllTables ()

    prywatna zabawa clearRoomDB () {GlobalScope.launch {appDB.clearAllTables () preferences.put (PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false) preferences.put (PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO}}}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.