Sala de persistencia biblioteca. Eliminar todos

181

¿Cómo puedo eliminar todas las entradas en una tabla específica usando la Biblioteca de persistencia de sala? Necesito abandonar la tabla, pero no puedo encontrar ninguna información sobre cómo hacerlo.

Solo cuando la base de datos está migrando o para cargar todas las entradas y eliminarlas :)

Sirelon
fuente
14
A partir de la habitación 1.1.0, puede usar el clearAllTables()que "elimina todas las filas de todas las tablas que están registradas en esta base de datos como entidades ()". He incluido esto como respuesta a continuación, pero estoy reproduciendo aquí para mayor visibilidad.
Dick Lucas

Respuestas:

445

Puede crear un método DAO para hacer esto.

@Dao 
interface MyDao {
    @Query("DELETE FROM myTableName")
    public void nukeTable();
}
yigit
fuente
3
Ah, no había pensado en eso. Supuse que @Queryse limitaba a cosas que devuelven conjuntos de resultados (similares a rawQuery()). ¡Muy genial!
CommonsWare
1
@yigit, ¿puedo solicitar que @Deleteno tome ningún parámetro y eliminar todo de la tabla? Estoy tratando de encontrar el rastreador de Room para archivar eso ...
Felipe Duarte
44
¡Cuidado! En cuanto a la versión de la sala alpha4, esta técnica provocará un error de construcción de gradle
yshahak
2
¿Qué tal Ids? Me gustó esto, pero los ID de tabla continúan incrementándose. En la caída de la tabla real, los ID también se descartan para comenzar desde 0 nuevamente.
Ioane Sharvadze
66
@yigit ¿Hay alguna forma de averiguar si la consulta se ejecutó correctamente o si hubo un error?
Aditya Ladwa
107

A partir de Room 1.1.0, puede usar clearAllTables () que:

Elimina todas las filas de todas las tablas que están registradas en esta base de datos como entidades ().

Dick Lucas
fuente
44
Tenga cuidado: clearAllTables () es asíncrono y no hay forma de saber cuándo se completa.
Alexey
2
@Alexey, pero ¿podría haber algún problema al intentar guardar algo después de clearAllTables? Como en, ¿solo intentará insertar DESPUÉS de la limpieza? Porque estoy bien con eso.
FirstOne
2
@FirstOne clearAllTables básicamente solo inicia una transacción en un nuevo hilo de fondo. Elimina todos los datos de las tablas y luego confirma esa transacción. Si comienza su transacción más tarde de lo que clearAllTables comienza, está bien. Dicho esto, si intenta insertar algunos datos justo después de llamar a clearAllTable, su inserción podría comenzar antes de que clearAllTable comience la transacción y perderá todos sus datos. Si necesita insertar datos nuevos justo después de llamar a clearAllTable, al menos agregue algún retraso.
Alexey
2
@Alexey ¿Hay alguna forma de usar un método de devolución de llamada o similar para determinar el estado de la transacción de eliminación? En otras palabras, si el estado de la transacción de eliminación está completo, continúe con el método de inserción de datos.
AJW
1
@AJW No, a partir de ahora, todavía no hay forma de saber cuándo se completó la operación. Si realmente necesita esta funcionalidad, es posible que desee probar algo como SELECT name FROM sqlite_master WHERE type='table'y luego manualmente DELETE FROM {TABLE}. Sin embargo, no he probado esto.
Alexey
33

Si desea eliminar una entrada de la tabla en la sala, simplemente llame a esta función,

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

Actualización: y si desea eliminar la tabla completa, llame a la siguiente función,

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

Nota: Aquí MyModel es un nombre de tabla.

Aman Gupta - ShOoTeR
fuente
recibí este error después de usar su error de código de actualización: un método DAO abstracto debe ser anotado con una y solo una de las siguientes anotaciones: Insertar, Eliminar, Consultar, Actualizar, RawQuery void delete ();
bramastaVic
12

Use clearAllTables () con RXJava como se muestra a continuación 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());


                }
            });
Adewale Balogun
fuente
4

Tuve problemas con eliminar todo el método al usar RxJava para ejecutar esta tarea en segundo plano. Así es como finalmente lo resolví:

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

y

fun deleteAllUsers() {
    return Maybe.fromAction(userDao::deleteAll)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe ({
            d("database rows cleared: $it")
        }, {
            e(it)
        }).addTo(compositeDisposable)
}
Micer
fuente
55
Cuando usa Kotlin, puede envolverlo en thread {}lugar de usarlo en el futx con RxJava
Erik
1

Combinando lo que dice Dick Lucas y agregando un reinicio automático de otras publicaciones de StackOverFlow, creo que esto puede 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()
        }
    }
Hamlet Leon
fuente
Para lo que vale, he encontrado que es más fácil hacer esto a través de context.deleteDatabase ("nombre") y luego simplemente reinstalar y repoblar la base de datos a través de Room.databaseBuilder (). AddCallback al primer acceso.
Bink
¿Qué es sqlite_sequence?
RoyalGriffin
0

Para utilizar la sala sin abusar de la @Queryanotación, primero use @Querypara seleccionar todas las filas y ponerlas en una lista, por ejemplo:

@Query("SELECT * FROM your_class_table")

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

Ponga su lista en la anotación de eliminación, por ejemplo:

@Delete

void deleteAllOfYourTable(List`<`your_class`>` your_class_list);
Dirk Fraanje
fuente
0

Así es como lo hice en Kotlin.

  1. Inyecte la habitación db en la actividad usando DI (Koin).

     private val appDB: AppDB by inject()
  2. Entonces simplemente puede llamar a clearAllTables ()

    private fun clearRoomDB () {GlobalScope.launch {appDB.clearAllTables () preferencias.put (PreferenceConstants.IS_UPLOADCATEGORIES_SAVED_TO_DB, false) preferencias.put (PreferenceConstants.IS_MEMBERHANDBOOK_SAVED_TO_DB, false)}}

VIVEK CHOUDHARY
fuente