Комната персистентной библиотеки. Удалить все


182

Как я могу удалить все записи в определенной таблице, используя Библиотеку комнат? Мне нужно удалить таблицу, но я не могу найти какую-либо информацию, как это сделать.

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


14
Начиная с Room 1.1.0 вы можете использовать clearAllTables()команду «удаляет все строки из всех таблиц, которые зарегистрированы в этой базе данных как лица ()». Я включил это как ответ ниже, но я воспроизвожу здесь для наглядности.
Дик Лукас

Ответы:


446

Вы можете создать метод DAO для этого.

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

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

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

4
Осторожно! что касается версии комнаты alpha4, эта техника приведет к сбою сборки gradle
yshahak

2
Как насчет Ids? Мне это понравилось, но идентификаторы таблиц продолжают увеличиваться. В реальной таблице идентификаторы сброса также сбрасываются, чтобы начать с 0 снова.
Иоанн Шарвадзе

6
@yigit Есть ли способ узнать, был ли запрос выполнен успешно или произошла ошибка?
Адитья Ладва

107

Начиная с Room 1.1.0вы можете использовать clearAllTables (), которая:

Удаляет все строки из всех таблиц, которые зарегистрированы в этой базе данных как лица ().


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

2
@ Алексей, но могут ли быть проблемы с попыткой сохранить что-либо после 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 должен быть аннотирован одной и только одной из следующих аннотаций: Insert, Delete, Query, Update, 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
Когда вы используете Kotlin, вы можете просто обернуть его 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 («name»), а затем просто повторно создать и заново заполнить базу данных с помощью 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 () Предпочтения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.