Бібліотека стійкості номерів. Видалити всі


182

Як я можу видалити всі записи з певної таблиці за допомогою бібліотеки стійкості кімнати? Мені потрібно скинути таблицю, але я не можу знайти жодної інформації, як це зробити.

Тільки коли база даних мігрує або завантажує всі записи та видаляє їх :)


14
Станом на номер 1.1.0 ви можете використовувати, clearAllTables()який "видаляє всі рядки з усіх таблиць, які зареєстровані в цій базі даних як об'єкти ()." Я включив це як відповідь нижче, але відтворюю тут для наочності.
Дік Лукас

Відповіді:


446

Для цього можна створити метод DAO.

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

3
Ах, я про це не думав. Я припускав, що @Queryце обмежено речами, які повертають набори результатів (подібні до rawQuery()). Дуже круто!
CommonsWare

1
@yigit чи можу я запитати, що @Deleteне має жодного параметра та видалити все з таблиці? Я намагаюся знайти трекер Кімнати, щоб подати це ...
Феліпе Дуарте

4
Стережись! що стосується версії альфа4 для кімнати, то ця методика призведе до помилки складання gradle
yshahak

2
Як щодо Ids? Мені це подобалося, але ідентифікатори таблиці продовжують збільшуватися. У реальній крапці таблиці знижуються ідентифікатори, щоб знову почати з 0.
Іоан Шавардзе

6
@yigit Чи є спосіб дізнатись, чи успішно працював запит чи помилка?
Aditya Ladwa

107

Станом на номер 1.1.0ви можете використовувати clearAllTables () який:

Видаляє всі рядки з усіх таблиць, які зареєстровані в цій базі даних як об'єкти ().


44
Будьте уважні: clearAllTables () є асинхронним, і немає можливості сказати, коли він завершується.
Олексій

2
@Alexey, але чи можуть виникнути проблеми при спробі зберегти щось після clearAllTables? Як і в, чи буде вона лише намагатися вставити ПІСЛЯ очищення? Бо я з цим добре.
Першийодин

2
@FirstOne clearAllTables в основному просто починає транзакцію з нового фонового потоку. Він видаляє всі дані з таблиць, а потім здійснює цю транзакцію. Якщо ви розпочнете транзакцію пізніше, ніж clearAllTables розпочне її, ви все в порядку. При цьому, якщо ви спробуєте вставити деякі дані відразу після виклику clearAllTable, ваша вставка може початися до того, як clearAllTable розпочне транзакцію, і ви втратите всі свої дані. Якщо вам потрібно вставити нові дані відразу після виклику clearAllTable, принаймні додайте деяку затримку.
Олексій

2
@Alexey Чи є спосіб використовувати метод зворотного виклику чи подібний метод для визначення стану транзакції видалення? Іншими словами, якщо стан транзакції видалити завершено, тоді перейдіть до методу вставки даних.
AJW

1
@AJW Ні, станом на сьогодні, досі немає способу сказати, коли операція завершена. Якщо вам справді потрібна ця функціональність, ви можете спробувати щось на зразок, SELECT name FROM sqlite_master WHERE type='table'а потім вручну DELETE FROM {TABLE}. Це ще не перевірено.
Олексій

33

Якщо ви хочете видалити запис із таблиці в кімнаті, просто зателефонуйте на цю функцію,

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

Оновлення. І якщо ви хочете видалити повну таблицю, зателефонуйте нижче,

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

Примітка. Тут MyModel - ім'я таблиці.


я отримав цю помилку після використання вашої помилки коду оновлення: Абстрактний метод DAO повинен бути помічений однією та лише однією з таких приміток: Вставити, Видалити, Запити, Оновити, RawQuery void delete ();
bramastaVic

12

Використовуйте clearAllTables () з RXJava, як показано нижче, для того, щоб уникнути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

У мене виникли проблеми з видаленням усіх методів при використанні RxJava для виконання цього завдання на задньому плані. Ось як я остаточно вирішив це:

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

і

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

5
Коли ви користуєтесь Котліном, ви можете просто загорнути його thread {}замість того, щоб збити RxJava
Ерік

1

Поєднуючи те, що говорить Дік Лукас, і додаючи автоматичний засіб скидання з інших публікацій StackOverFlow, я думаю, що це може працювати:

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

Для чого це варто, я вважаю, що найпростіше це зробити через context.deleteDatabase ("ім'я"), а потім просто відновити та повторно запустити базу даних через Room.databaseBuilder (). AddCallback при першому доступі.
Бінк

Що таке sqlite_sequence?
RoyalGriffin

0

Щоб скористатися Кімнатою без зловживань із @Queryанотацією, спочатку @Queryвиберіть усі рядки та помістіть їх у список, наприклад:

@Query("SELECT * FROM your_class_table")

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

Помістіть його список у примітку про видалення, наприклад:

@Delete

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

0

Ось як я це зробив у Котліні.

  1. Введіть кімнату db в діяльність, використовуючи DI (Koin).

     private val appDB: AppDB by inject()
  2. Тоді ви можете просто зателефонувати clearAllTables ()

    приватне задоволення clearRoomDB () {GlobalScope.launch {appDB.clearAllTables () preferences.put (PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false) preferences.put (PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO_DB, false)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.