Biblioteca de persistência do quarto. Excluir tudo


181

Como excluir todas as entradas de uma tabela específica usando a Biblioteca de persistência da sala? Preciso descartar a tabela, mas não consigo encontrar nenhuma informação sobre como fazer isso.

Somente quando o banco de dados estiver migrando ou para carregar todas as entradas e excluí-las :)


14
Na sala 1.1.0, você pode usar o clearAllTables()que "exclui todas as linhas de todas as tabelas registradas neste banco de dados como entidades ()". Incluí isso como resposta abaixo, mas estou reproduzindo aqui para obter visibilidade.
Dick Lucas

Respostas:


445

Você pode criar um método DAO para fazer isso.

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

3
Ah, eu não tinha pensado nisso. Eu assumi que isso @Queryse limitava a coisas que retornam conjuntos de resultados (semelhante a rawQuery()). Muito legal!
CommonsWare

1
@yigit posso solicitar que @Deletenão use nenhum parâmetro e excluir tudo da tabela? Eu estou tentando encontrar rastreador do quarto para o arquivo que ...
Felipe Duarte

4
Cuidado! quanto à versão alpha4 da sala, essa técnica levará a uma falha na compilação do gradle
yshahak

1
Que tal Ids? Eu fiz isso, mas os IDs de tabela continuam aumentando. Na queda real da tabela, os IDs também são eliminados para começar novamente a partir de 0.
Ioane Sharvadze

6
@yigit Existe uma maneira de descobrir se a consulta foi executada com sucesso ou se ocorreu um erro?
Aditya Ladwa #

107

A partir da sala, 1.1.0você pode usar clearAllTables () que:

Exclui todas as linhas de todas as tabelas registradas neste banco de dados como entidades ().


44
Cuidado: clearAllTables () é assíncrono e não há como saber quando é concluído.
21418 Alexey

2
@ Alex, mas poderia haver algum problema ao tentar salvar algo após o clearAllTables? Como em, ele apenas tentará inserir APÓS a limpeza? Porque eu estou bem com isso.
FirstOne 31/08/18

2
@FirstOne clearAllTables basicamente apenas inicia uma transação em um novo thread em segundo plano. Exclui todos os dados das tabelas e confirma essa transação. Se você iniciar sua transação depois que o clearAllTables iniciar, você estará bem. Dito isto, se você tentar inserir alguns dados logo após chamar clearAllTable, sua inserção poderá começar antes que clearAllTable inicie a transação e você perderá todos os seus dados. Se você precisar inserir novos dados logo após chamar clearAllTable, adicione pelo menos algum atraso.
314 Alexey

2
@Alexey Existe alguma maneira de usar um método de retorno de chamada ou semelhante para determinar o estado da transação de exclusão? Em outras palavras, se o estado da transação de exclusão estiver completo, continue com o método de inserção de dados.
AJW

1
@AJW Não, a partir de agora, ainda não há como saber quando a operação está concluída. Se você realmente precisar dessa funcionalidade, poderá tentar algo parecido SELECT name FROM sqlite_master WHERE type='table'e, em seguida, manualmente DELETE FROM {TABLE}. Ainda não testei isso.
27419 Alexey

33

Se quiser excluir uma entrada da tabela na sala, basta chamar esta função,

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

Atualização: e se você deseja excluir a tabela completa, chame a função abaixo,

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

Nota: Aqui MyModel é um nome de tabela.


Eu recebi este erro após usar o erro de código de atualização: Um método abstrato do DAO deve ser anotado com uma e apenas uma das seguintes anotações: Inserir, Excluir, Consultar, Atualizar, RawQuery void delete ();
bramastaVic

12

Use clearAllTables () com RXJava, como abaixo, para evitarjava.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

Eu tive problemas com excluir todos os métodos ao usar o RxJava para executar esta tarefa em segundo plano. Foi assim que finalmente resolvi:

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

e

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

5
Quando você estiver usando o Kotlin, você pode envolvê-lo em thread {}vez de futzing com o RxJava
Erik

1

Combinando o que Dick Lucas diz e adicionando uma redefinição automática de outras postagens StackOverFlow, acho que isso pode funcionar:

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

Pelo que vale, achei mais fácil fazer isso via context.deleteDatabase ("name") e, em seguida, simplesmente restabelecer e repovoar o banco de dados por meio do Room.databaseBuilder (). AddCallback após o primeiro acesso.
Bink

O que é sqlite_sequence?
RoyalGriffin 15/04

0

Para usar a Sala sem abusar da @Queryanotação, primeiro use @Querypara selecionar todas as linhas e colocá-las em uma lista, por exemplo:

@Query("SELECT * FROM your_class_table")

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

Coloque sua lista na anotação de exclusão, por exemplo:

@Delete

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

0

Aqui está como eu fiz isso em Kotlin.

  1. Injete o banco de dados db na atividade usando DI (Koin).

     private val appDB: AppDB by inject()
  2. Então você pode simplesmente chamar clearAllTables ()

    diversão privada clearRoomDB () {GlobalScope.launch {appDB.clearAllTables () Preferences.put (PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false) Preferences.put (PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO_DB, false)}}

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.