interfaz - java jframe tutorial pdf
MigraciĆ³n de la base de datos de la sala si solo se agrega una nueva tabla (6)
No supongamos que tengo una base de datos simple de Room:
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Ahora, estoy agregando una nueva entidad:
Pet
and bumping version to 2:
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
}
Por supuesto, Room genera una excepción:
java.lang.IllegalStateException: A migration from 1 to 2 is necessary.
Suponiendo que no he cambiado
User
clase de
User
(por lo que todos los datos están seguros), tengo que proporcionar la migración que solo crea una nueva tabla.
Entonces, estoy buscando clases generadas por Room, buscando consultas generadas para crear mi nueva tabla, copiando y pegando en la migración:
final Migration MIGRATION_1_2 =
new Migration(1, 2) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS `Pet` (`name` TEXT NOT NULL, PRIMARY KEY(`name`))");
}
};
Sin embargo, me parece inconveniente hacerlo manualmente. ¿Hay alguna manera de decirle a Room? No estoy tocando ninguna de las tablas existentes, por lo que los datos están seguros. ¿Por favor crear migración para mí?
En este caso, no necesita hacer una migración, puede llamar a .fallbackToDestructiveMigration () cuando crea una instancia de base de datos.
Ejemplo:
instance = Room.databaseBuilder(context, AppDatabase.class, "database name").fallbackToDestructiveMigration().build();
Y no olvide cambiar la versión de la base de datos.
Lo sentimos, Room no admite la creación automática de tablas sin pérdida de datos.
Es obligatorio escribir la migración. De lo contrario, borrará todos los datos y creará la nueva estructura de la tabla.
Puede agregar el siguiente comando gradle a su configuración predeterminada en su app.gradle:
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":
"$projectDir/schemas".toString()]
}
}
Cuando ejecute esto, compilará una lista de nombres de tablas con sus correspondientes declaraciones CREATE TABLE desde las cuales puede copiar y pegar en sus objetos de migración. Puede que tenga que cambiar los nombres de la tabla.
Por ejemplo, esto es de mi esquema generado:
"tableName": "assets",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`asset_id` INTEGER NOT NULL, `type` INTEGER NOT NULL, `base` TEXT NOT NULL, `name` TEXT NOT NULL, PRIMARY KEY(`asset_id`))"
Y así copio, pego la instrucción createSql y cambio el ''$ {TABLE_NAME}'' a ''activos'' el nombre de la tabla, y listo.
Puedes hacerlo de esta manera
@Database(entities = {User.class, Pet.class}, version = 2)
abstract class AppDatabase extends RoomDatabase {
public abstract Dao getDao();
public abstract Dao getPetDao();
}
El resto será el mismo que ha mencionado anteriormente.
db = Room.databaseBuilder(this, AppDatabase::class.java, "your_db")
.addMigrations(MIGRATION_1_2).build()
Referencia - Para más
Tal vez en este caso (si solo ha creado una nueva tabla sin cambiar otras), ¿puede hacer esto sin crear ninguna migración?
La sala
NO
tiene un buen sistema de migración, al menos hasta
2.1.0-alpha03
.
Se espera que tenga un mejor sistema de migración en
2.2.0
Entonces, hasta que tengamos un mejor sistema de migración, hay algunas soluciones para tener migraciones fáciles en la sala.
Como no existe un método como
@Database(createNewTables = true)
o
MigrationSystem.createTable(User::class)
, que debería haber uno u otro, la única forma posible es ejecutar
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
dentro de su método de
migrate
.
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
Para superar el script SQL , tienes 4 formas
1. Escribe por ti mismo
Básicamente, debe escribir el script anterior que coincidirá con el script que genera Room. De esta manera es posible, no factible. (Considere que tiene 50 campos)
2. Esquema de exportación
Si incluye
exportSchema = true
dentro de su anotación
@Database
, Room generará un esquema de base de datos dentro de / esquemas de su carpeta de proyecto.
El uso es
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
Asegúrese de haber incluido las líneas siguientes en
build.grade
de su módulo de aplicación
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
Cuando ejecuta o crea el proyecto, obtendrá un archivo JSON
2.json
, que tiene todas las consultas dentro de la base de datos de su sala.
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
Por lo tanto, puede incluir el
createSql
anterior dentro de su método de
migrate
.
3. Obtenga una consulta de AppDatabase_Impl
Si no desea exportar el esquema, aún puede obtener la consulta ejecutando o
AppDatabase_Impl.java
el proyecto que generará el archivo
AppDatabase_Impl.java
.
y dentro del archivo especificado que puede tener.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
Dentro del método
createAllTables
, habrá scripts de creación de todas las entidades.
Puede obtenerlo e incluirlo dentro de su método de
migrate
.
4. Procesamiento de anotaciones.
Como puede suponer, Room genera todos los
schema
mencionados anteriormente y los archivos
AppDatabase_Impl
dentro del tiempo de compilación y con el procesamiento de anotaciones que agrega con
kapt "androidx.room:room-compiler:$room_version"
Eso significa que también puede hacer lo mismo y crear su propia biblioteca de procesamiento de anotaciones que genera todas las consultas de creación necesarias para usted.
La idea es hacer una biblioteca de procesamiento de anotaciones para las anotaciones de
@Entity
de
@Entity
y
@Database
.
Tome una clase que está anotada con
@Entity
por ejemplo.
Estos son los pasos que deberás seguir
-
Cree un nuevo
StringBuilder
y agregue "CREAR TABLA SI NO EXISTE" -
Obtenga el nombre de la tabla de
class.simplename
o por el campo@Entity
de@Entity
.StringBuilder
a suStringBuilder
-
Luego, para cada campo de su clase, cree columnas de SQL.
Tome el nombre, tipo, nulabilidad del campo por el campo en sí o por la anotación
@ColumnInfo
. Para cada campo, debe agregar el estiloid INTEGER NOT NULL
de una columna a suStringBuilder
. -
Agregar claves primarias por
@PrimaryKey
-
Agregue
ForeignKey
eIndices
si existe. - Después de terminar, conviértalo a cadena y guárdelo en una nueva clase que desee usar. Por ejemplo, guárdelo como a continuación
public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
Entonces, puedes usarlo como
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
Hice una biblioteca para mí que puede consultar e incluso usar en su proyecto. Tenga en cuenta que la biblioteca que hice no está llena y solo cumple mis requisitos para la creación de tablas.
RoomExtension para una mejor migración
Aplicación que usa RoomExtension
Espero que haya sido útil.