[Jetpack] Use Room Migration para actualizar la base de datos y exportar el archivo de esquema (Introducción del archivo de esquema | Generar configuración de archivo de esquema | Generar proceso de archivo de esquema)





1. Introducción al archivo de esquema



Para usar Room Migration para actualizar la base de datos , debe escribir una serie de clases de migración de migración de acuerdo con la versión actual de la base de datos y la versión de destino, y generar un archivo de esquema actualizado, que es un archivo en formato json, que contiene el siguiente contenido:

  • Información de la versión: incluida la versión actual y la versión de destino;
  • Cree una declaración de tabla: que incluya la definición y la información de campo de la tabla recién agregada ;
  • Declaración de eliminación de tabla: incluido el nombre de la tabla que se eliminará;
  • Modificar declaración de tabla: incluyendo el nombre de la tabla a modificar y la información de definición del campo a modificar;
  • Insertar declaración de datos: incluya el nombre de la tabla que necesita insertar datos y los datos que se insertarán;
  • Eliminar declaración de datos: incluido el nombre de la tabla que necesita eliminar datos y las condiciones para la eliminación;

El archivo de esquema es un archivo que describe la estructura de la base de datos de Room.A través de este archivo, los desarrolladores pueden comprender fácilmente los registros de cambios históricos de la base de datos y solucionar problemas;

El archivo de esquema define la estructura de elementos como tablas, columnas e índices en la base de datos y contiene secuencias de comandos SQL para crear y actualizar la base de datos;


Use la migración de Room para actualizar la base de datos, y el archivo de esquema generado generalmente se realiza a través de la tarea roomExportSchema en el script de compilación de Gradle, que exportará el archivo de esquema al directorio especificado, que debe configurarse en el script de compilación build.gradle;





2. Generar la configuración del archivo de esquema



Al actualizar la base de datos de salas, puede utilizar la herramienta de migración de salas para generar un archivo de esquema;

Si desea exportar el archivo de esquema, debe establecer el parámetro exportSchema = true en la anotación @Database de la clase de implementación de RoomDatabase ;

@Database(entities = [Student::class], version = 3, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
    
    

En el blog anterior, el parámetro exportSchema se estableció en falso y el archivo de esquema no se exportó;


Además, es necesario configurar la ubicación de generación del archivo Schema en el script de compilación build.gradle y configurar parámetros en el nivel "android/defaultConfig/javaCompileOptions/annotationProcessorOptions" ;"room.schemaLocation": "$projectDir/schemas".toString()

La jerarquía de configuración completa es la siguiente:

android {
    
    
    namespace 'kim.hsl.rvl'
    compileSdk 32

    defaultConfig {
    
    
        applicationId "kim.hsl.rvl"
        minSdk 21
        targetSdk 32

        javaCompileOptions {
    
    
            annotationProcessorOptions {
    
    
                // 指定 Room Migration 升级数据库导出的 Schema 文件位置
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
}

projectDir es el directorio raíz del módulo Módulo, el directorio de esquemas generados y src, build, build.gradle son archivos en el mismo nivel;





3. El proceso de generación del archivo Schema




1. Versión 1 de la base de datos: ejecute la aplicación por primera vez


Aplicación que ejecuta la base de datos versión 1, primera ejecución,

        fun inst(context: Context): StudentDatabase {
    
    
            if (!::instance.isInitialized) {
    
    
                synchronized(StudentDatabase::class) {
    
    
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        //.addMigrations(MIGRATION_1_2)
                        //.addMigrations(MIGRATION_2_3)
                        //.fallbackToDestructiveMigration()
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()
                }
            }
            return instance;
        }

Comente los campos recién agregados en la clase de entidad Entidad;

    /**
     * 性别字段
     * 数据库表中的列名为 sex
     * 数据库表中的类型为 INTEGER 文本类型
     */
    /*@ColumnInfo(name = "sex", typeAffinity = ColumnInfo.INTEGER)
    var sex: Int = 0*/

    /**
     * degree字段
     * 数据库表中的列名为 sex
     * 数据库表中的类型为 INTEGER 文本类型
     */
    /*@ColumnInfo(name = "degree", typeAffinity = ColumnInfo.INTEGER)
    var degree: Int = 0*/

Establezca la versión del bloque de datos en 1:

@Database(entities = [Student::class], version = 1, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
    
    

Ejecute la aplicación por primera vez para generar el archivo de esquema 1.json de la versión 1 de la base de datos;

La ubicación donde se genera el archivo de esquema es la ruta "app/schemes/package name/1.json";

{
    
    
  "formatVersion": 1,
  "database": {
    
    
    "version": 1,
    "identityHash": "acca4b709e6c8b9b88d8328be36b9032",
    "entities": [
      {
    
    
        "tableName": "student",
        "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL)",
        "fields": [
          {
    
    
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "name",
            "columnName": "name",
            "affinity": "TEXT",
            "notNull": false
          },
          {
    
    
            "fieldPath": "age",
            "columnName": "age",
            "affinity": "INTEGER",
            "notNull": true
          }
        ],
        "primaryKey": {
    
    
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'acca4b709e6c8b9b88d8328be36b9032')"
    ]
  }
}

inserte la descripción de la imagen aquí


2. Actualice la versión 1 de la base de datos a la versión 2 de la base de datos: ejecute la aplicación por segunda vez


Primero, configure los campos en la clase de entidad Entity y agregue el campo de sexo en función de la versión 1 de la base de datos;

    /**
     * 性别字段
     * 数据库表中的列名为 sex
     * 数据库表中的类型为 INTEGER 文本类型
     */
    @ColumnInfo(name = "sex", typeAffinity = ColumnInfo.INTEGER)
    var sex: Int = 0

Luego, defina la clase de migración de migración que actualiza la versión 1 de la base de datos a la versión 2 de la base de datos.

        /**
         * 数据库版本 1 升级到 版本 2 的迁移类实例对象
         */
        val MIGRATION_1_2: Migration = object : Migration(1, 2) {
    
    
            override fun migrate(database: SupportSQLiteDatabase) {
    
    
                Log.i("Room_StudentDatabase", "数据库版本 1 升级到 版本 2")
                database.execSQL("alter table student add column sex integer not null default 1")
            }
        }

Luego, llame a RoomDatabase.Builder#addMigrations para agregar la clase de migración de migración definida anteriormente;

        fun inst(context: Context): StudentDatabase {
    
    
            if (!::instance.isInitialized) {
    
    
                synchronized(StudentDatabase::class) {
    
    
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        .addMigrations(MIGRATION_1_2)
                        //.addMigrations(MIGRATION_2_3)
                        //.fallbackToDestructiveMigration()
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()
                }
            }
            return instance;
        }

Finalmente, modifique la versión de la base de datos a 2,

@Database(entities = [Student::class], version = 2, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
    
    

El archivo de esquema generado para actualizar la versión 1 de la base de datos a la versión 2 de la base de datos es el siguiente:

{
    
    
  "formatVersion": 1,
  "database": {
    
    
    "version": 2,
    "identityHash": "84fb235f8062b0a6b0c8d1a6d1035c4f",
    "entities": [
      {
    
    
        "tableName": "student",
        "createSql": "CREATE TABLE IF NOT EXISTS `${
      
      TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL, `sex` INTEGER NOT NULL)",
        "fields": [
          {
    
    
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "name",
            "columnName": "name",
            "affinity": "TEXT",
            "notNull": false
          },
          {
    
    
            "fieldPath": "age",
            "columnName": "age",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "sex",
            "columnName": "sex",
            "affinity": "INTEGER",
            "notNull": true
          }
        ],
        "primaryKey": {
    
    
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '84fb235f8062b0a6b0c8d1a6d1035c4f')"
    ]
  }
}

inserte la descripción de la imagen aquí


3. Actualice la versión 2 de la base de datos a la versión 3 de la base de datos: ejecute la aplicación por tercera vez


Primero, configure los campos en la clase de entidad Entity y agregue el campo de grado en base a la versión 2 de la base de datos;

    /**
     * 性别字段
     * 数据库表中的列名为 sex
     * 数据库表中的类型为 INTEGER 文本类型
     */
    @ColumnInfo(name = "sex", typeAffinity = ColumnInfo.INTEGER)
    var sex: Int = 0

    /**
     * degree字段
     * 数据库表中的列名为 sex
     * 数据库表中的类型为 INTEGER 文本类型
     */
    @ColumnInfo(name = "degree", typeAffinity = ColumnInfo.INTEGER)
    var degree: Int = 0

Luego, defina la clase de migración de migración que actualiza la versión 2 de la base de datos a la versión 3 de la base de datos.

        /**
         * 数据库版本 2 升级到 版本 3 的迁移类实例对象
         */
        val MIGRATION_2_3: Migration = object : Migration(2, 3) {
    
    
            override fun migrate(database: SupportSQLiteDatabase) {
    
    
                Log.i("Room_StudentDatabase", "数据库版本 2 升级到 版本 3")
                database.execSQL("alter table student add column degree integer not null default 1")
            }
        }

Luego, llame a RoomDatabase.Builder#addMigrations para agregar la clase de migración de migración definida anteriormente;

        fun inst(context: Context): StudentDatabase {
    
    
            if (!::instance.isInitialized) {
    
    
                synchronized(StudentDatabase::class) {
    
    
                    // 创建数据库
                    instance = Room.databaseBuilder(
                        context.applicationContext,
                        StudentDatabase::class.java,
                        "student_database.db")
                        .addMigrations(MIGRATION_1_2)
                        .addMigrations(MIGRATION_2_3)
                        //.fallbackToDestructiveMigration()
                        .allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
                                                  // 如果要在主线程操作数据库需要调用该函数
                        .build()
                }
            }
            return instance;
        }

Finalmente, modifique la versión de la base de datos a 3,

@Database(entities = [Student::class], version = 2, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
    
    

El archivo de esquema generado para actualizar la versión 2 de la base de datos a la versión 3 de la base de datos es el siguiente:

{
    
    
  "formatVersion": 1,
  "database": {
    
    
    "version": 3,
    "identityHash": "d88859680a038f5155613d94de7888cc",
    "entities": [
      {
    
    
        "tableName": "student",
        "createSql": "CREATE TABLE IF NOT EXISTS `${
      
      TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL, `sex` INTEGER NOT NULL, `degree` INTEGER NOT NULL)",
        "fields": [
          {
    
    
            "fieldPath": "id",
            "columnName": "id",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "name",
            "columnName": "name",
            "affinity": "TEXT",
            "notNull": false
          },
          {
    
    
            "fieldPath": "age",
            "columnName": "age",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "sex",
            "columnName": "sex",
            "affinity": "INTEGER",
            "notNull": true
          },
          {
    
    
            "fieldPath": "degree",
            "columnName": "degree",
            "affinity": "INTEGER",
            "notNull": true
          }
        ],
        "primaryKey": {
    
    
          "columnNames": [
            "id"
          ],
          "autoGenerate": true
        },
        "indices": [],
        "foreignKeys": []
      }
    ],
    "views": [],
    "setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd88859680a038f5155613d94de7888cc')"
    ]
  }
}

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/han1202012/article/details/131048359
Recomendado
Clasificación