¡Cómo migrar manualmente la base de datos de Android Room! | Autor: Shehan Atukorala | Noviembre de 2021
¿Quiere utilizar la base de datos SQLite en su aplicación de Android? Si es así, utilice la popular biblioteca de persistencia: Room será su mejor opción. Pero, ¿qué debe hacer cuando realiza cambios en la clase de entidad Room y desea que esos cambios se reflejen en la base de datos SQLite?
Bueno, ¡tienes que ejecutar algunas migraciones de base de datos! En este artículo, analizaremos cómo crear y ejecutar migraciones de habitaciones en el desarrollo de Android. Así que no te demores más, ¡vayamos directo a ello!
Primero lo haremoselectrónicouna aplicación de Android de muestra para algunas migraciones de habitaciones. Para hacer esto, simplemente cree una nueva aplicación de Android en Android Studio (si aún no la ha instalado, haga clic aquí para descargar). Elija una actividad vacía como la plantilla de inicio de este proyecto de Android, como se muestra a continuación:
Una vez que nuestra aplicación de Android está configurada, podemos centrar nuestra atención en el nivel del proyecto. build.gradle
Archivar y agregar las siguientes dependencias:
dependencies { ...def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room
implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room
implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture
implementation "androidx.room:room-guava:$room_version" // optional - Test helpers
testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration
implementation "androidx.room:room-paging:2.4.0-beta01" ...
}
A continuación, debemos sincronizar el proyecto con el actualizado build.gradle
Cree el archivo haciendo clic en el botón «Sincronizar proyecto con archivo Gradle» como se muestra a continuación:
Por cierto, creamos una clase de base de datos que almacenará información de la base de datos, que se utilizará para conectarse a la base de datos SQLite utilizando la biblioteca de persistencia de Room.
Primero, necesitamos una clase modelo, que podemos usar para mapear una tabla en la base de datos.Vamos a crear uno models
Empaquete y agregue un archivo llamado Vehicle.java
En él, necesitamos el siguiente código para definir la clase de Vehículo:
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;@Entity(tableName="vehicle")
public class Vehicle { @PrimaryKey(autoGenerate=true)
@ColumnInfo(name="id")
@NonNull
private int id;
@ColumnInfo(name="name")
@NonNull
private String name; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Vehicle{" +
"id=" + id +
", name='" + name + ''' +
'}';
}
}
Repasemos lo que acabamos de agregar:
- @
Entity(tableName="")
: estaEntity
La anotación indica que esta clase se asignará a una tabla en la base de datos @PrimaryKey(autoGenerated=True)
: Este comentario indicaid
La columna será la clave principal.Además, la identificación se generará automáticamente, comoautoGenerated=True
Opciones@ColumnInfo(name="")
: Se utiliza para especificar el nombre de la columna en la tabla de la base de datos que se asignará al campo en este POJO@NonNull
: Se utiliza para garantizar que el campo no pueda contener valores nulos en la base de datos
A continuación, agreguemos una clase DAO a esta clase de vehículo.Para esto, primero debemos agregar un paquete llamado dao
Vaya al paquete raíz de origen y cree un archivo llamado VehicleDAO.java
dentro. Después de eso, podemos agregar lo siguiente a este archivo recién creado:
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;import com.coding.informer.roommanualmigrationexample.models.Vehicle;import java.util.List;@Dao
public interface VehicleDAO {
@Query("SELECT * FROM vehicle")
ListgetAll(); @Query("SELECT * FROM vehicle WHERE id in (:findVehicleId)")
Vehicle findById(int findVehicleId); @Insert
void insertAll(Vehicle... assetEntries); @Insert
void insertAsset(Vehicle asset); @Delete
void delete(Vehicle asset);
}
Esta clase DAO es como una puerta de enlace, entre la clase Vehicle en el lado de la aplicación y vehicle
Tabla en el lado de la base de datos.Nos permite vehicle
Table (para obtener más información sobre las operaciones CRUD, consulte este enlace), al tiempo que garantiza la coherencia de los datos entre los objetos de la clase Java y las entradas de la tabla de la base de datos.
Después de construir nuestra clase DAO, podemos dirigir nuestra atención a nuestra clase de base de datos.Primero, vamos database
Empaquete y cree una nueva clase llamada AppDatabase
.En él, escribamos el siguiente código:
import androidx.room.AutoMigration;
import androidx.room.Database;
import androidx.room.RenameTable;
import androidx.room.RoomDatabase;
import androidx.room.migration.AutoMigrationSpec;import com.coding.informer.roommanualmigrationexample.dao.VehicleDAO;
import com.coding.informer.roommanualmigrationexample.models.Vehicle;@Database(version=4, entities={Vehicle.class})
public abstract class AppDatabase extends RoomDatabase{
public abstract VehicleDAO getVehicleDAO(); public static final String NAME = "example_db";}
Básicamente estamos agregando @Database
Un comentario utilizado para declarar nuestra base de datos.Contiene la versión de la base de datos y el nombre de la base de datos en el propio comentario, asignado a NAME
sitio.
A continuación, debemos definir la migración que se ejecutará en la base de datos.Primero crea un paquete llamado migrations
Dentro database
paquete.Luego, crea un archivo llamado Migration1
En ese paquete. Finalmente, agregue el siguiente código al archivo:
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;public class Migration1 { public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE `vehicle` (`id` INTEGER NOT NULL, "
+ "`name` TEXT NOT NULL, PRIMARY KEY(`id`))");
}
};
}
dentro MIGRATION_1_2
Instancia de migración, tabla vehicle
Fue creado con la columna específica de arriba. Tenga en cuenta que cada vez que cambia una clase de entidad Java, se debe ejecutar una nueva migración que refleje los cambios en la base de datos. Además, la versión de migración debe cambiarse utilizando el siguiente formato: new Migration({CurrentVersion}, {CurrentVersion + 1})
.
¡estupendo! Entonces ahora tenemos nuestra clase modelo (Vehicle.java
), Clase DAO (VehicleDAO.java
) Y clase de base de datos (AppDatabase.java
), ahora podemos establecer una conexión de base de datos en nuestra actividad principal.
Agreguemos el siguiente código a nuestro MainActivity.java
documento:
import androidx.appcompat.app.AppCompatActivity;
import androidx.room.Room;import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;import com.coding.informer.roommanualmigrationexample.dao.VehicleDAO;
import com.coding.informer.roommanualmigrationexample.database.AppDatabase;
import com.coding.informer.roommanualmigrationexample.models.Vehicle;import java.util.List;import static com.coding.informer.roommanualmigrationexample.database.migrations.Migration1.MIGRATION_1_2;
import static com.coding.informer.roommanualmigrationexample.database.migrations.Migration1.MIGRATION_2_3;
import static com.coding.informer.roommanualmigrationexample.database.migrations.Migration1.MIGRATION_3_4;public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); AsyncTask.execute(() -> {
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "example_db")
.addMigrations(MIGRATION_1_2).build();
});
}
}
Por debajo del estándar super.onCreate(savedInstanceState)
line es la lógica utilizada para conectarse a la base de datos mediante Room.usar databaseBuilder()
Resultado en la obtención de una nueva instancia de base de datos.Después de la migración especificada Migration1
El archivo se utiliza para importar la migración que se ejecutará cuando la base de datos se actualice al estado actual de la aplicación. finalmente, build()
El método se utiliza para crear la instancia de la base de datos.
Ahora podemos agregar una segunda migración a vehicle
Tabla de base de datos.Agregue el siguiente código a Migration1
Cree los archivos para la segunda migración:
public static final Migration MIGRATION_2_3 = new Migration(2, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `vehicle` ADD COLUMN `model` INTEGER NOT NULL DEFAULT 0");
}
};
Lo que está haciendo esta migración es agregar una columna llamada model
llegar vehicle
Uso de mesa ALTER TABLE
Declaración SQL.Tenga en cuenta que para hacer la columna NOT NULL
Debemos especificar un valor predeterminado, en este caso 0.
Antes de ejecutar esta migración, debemos reflejar este cambio en la clase Vehicle, porque antes de ejecutar la migración, debemos hacer que el objeto de la clase Java refleje el cambio de migración.Así que revisemos la clase Vehículo y agreguemos model
Los campos y los captadores y definidores correspondientes son los siguientes:
@ColumnInfo(name="model")
@NonNull
private String model;@NonNull
public String getModel() {
return model;
}public void setModel(@NonNull String model) {
this.model = model;
}
Como última cosa, necesitamos aumentar la versión de la base de datos a 3 en nuestra base de datos. AppDatabase
Clase como esta:
@Database(version=3, entities={Vehicle.class})
public abstract class AppDatabase extends RoomDatabase{
...
}
Ahora, para ejecutar esta migración, debemos agregar la migración a MainActivity
Clase como esta:
AsyncTask.execute(() -> {
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "example_db")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
});
Solo haciendo esto, Room recibirá y ejecutará nuestra migración.
¡estupendo!Como se encuentra en la vista del inspector de la base de datos a continuación, hemos agregado con éxito model
Campo a vehicle
Ahora tabla:
model
Campo agregado a vehicle
¡mesa! 🚀Ahora para la migración final, lo eliminaremos. model
La columna que acabamos de agregar.Ir a Migration1
Class y agregue la siguiente migración:
public static final Migration MIGRATION_3_4 = new Migration(3, 4) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE `vehicle`");
database.execSQL("CREATE TABLE `vehicle` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`id`))");
}
};
Como puede ver arriba, actualmente no hay una forma directa de eliminar columnas de una base de datos SQLite usando Room.Entonces, ahora, la solución que usamos es eliminar toda la tabla, y luego, cuando no hay model
sitio. No es perfecto, pero funciona 😅
Recuerda agregar MIGRATION_3_4
mover a .addMigrations()
Lista MainActivity
Clasifique y aumente la versión de la base de datos a 4 AppDatabase
Clase, como hicimos para la segunda migración.
Finalmente, ejecute la aplicación y navegue hasta la vista del Inspector de la base de datos y busque model
¡desaparecido!
model
Campo de vehicle
¡mesa! ✔¡Entonces lo tienes! Si hiciste esto, date una palmada en la espalda, porque ahora sabes cómo migrar manualmente usando la aplicación Room para Android🚀🎉
¡Felicidades! Ha aprendido con éxito cómo migrar manualmente utilizando la aplicación Room para Android. Si necesita acceder al código fuente de esta aplicación, puede acceder a él visitando su enlace de GitHub.
Bueno, ¡este es este artículo! Gracias por su interés en este artículo. Si tiene alguna pregunta o inquietud, no dude en comentar este artículo y le responderé cuando tenga tiempo.
Si este artículo te resulta útil, compártelo y asegúrate de seguirme. Gorjeo Y GitHub, conéctate conmigo en LinkedIn y suscríbete a mi canal de Youtube.