Android room数据库注解、迁移

注解

@Entity:使用Room定义一个数据实体User(带Entity注解的类),一个Entity表由主键和一个或多个列组成,User中的每个实例都代表着User表中的一行,tableName后面为表名,在不指定表名的情况下,默认将类名作为数据表的名称。
@ColumnInfo:Room默认使用字段名称作为列名称,如需更改,采用@ColumnInfo注解设置name属性(列名)。

 @ColumnInfo(name = "user_name",typeAffinity = ColumnInfo.TEXT,defaultValue = "默认值")

@Ignore:表示会忽略这个字段,不进行记录
@PrimaryKey :每一个实体类都需要一个唯一的标识即主键。
@NonNull:该字段不可为空
@Embedded :实体类中引用其它实体类
Room 不允许对象引用,通过@TypeConverter自定义类型转换器
@Embedded——引用其它实体类:假如实体类中包含了多个同一类型的嵌入字段(比如一个人User拥有两本Book),我们可以通过设置prefix属性来保持每列的唯一性。Room会将提供的值添加到嵌入对象的每个列名的开头。

//@Embedded(prefix = "one"),这个是区分唯一性的,
//比如说一这个人有2本书并添加了tag,那么在数据表中就会以prefix+属性值命名
@Embedded(prefix = "one")
private Book address;
@Embedded(prefix = "two")
private Book address;

@Dao: 使用@Dao注解定义为一个BaseDao接口,增加基本的插入、删除、修改方法,再定义一个UserDao去扩展BaseDao接口,增加需要的方法。
@Insert:插入,可以定义将其参数插入数据库中的相应表的方法

OnConflictStrategy.REPLACE:冲突策略是取代旧数据同时继续事务
OnConflictStrategy.ROLLBACK:冲突策略是回滚事务
OnConflictStrategy.ABORT:冲突策略是终止事务
OnConflictStrategy.FAIL:冲突策略是事务失败
OnConflictStrategy.IGNORE:冲突策略是忽略冲突
最新代码中ROLLBACKFAIL 已经deprecated了,使用ABORT替代

@Delete:删除,可以定义用于从数据库表中删除特定行的方法
@Update:修改,可以定义用于更新数据库表中特定行的方法
@Query: 查询,可以从应用的数据库查询指定数据,用于更加复杂的插入、删除、更新操作

@DataBase:定义用户保存数据库的MyDataBase类,定义数据库配置。
@exportSchema:是否导出数据库表,默认true
如果不指定,需要将exportSchema = false,或者在app的build.gradle里设置对应的路径,否则会出现如下报错

Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide `room.schemaLocation` annotation processor argument OR set exportSchema to false.

        //指定room.schemaLocation生成的文件路径, java环境(两者选一,看项目环境)
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }


        //指定room.schemaLocation生成的文件路径, kotlin环境 (两者选一,看项目环境)
        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }
   }

@Database(entities = {User.class, Book.class}, version = 2,exportSchema = false)

@DeleteTable:删除数据表
DROP TABLE user_table
@RenameTable: 重命名数据表
database.execSQL("RENAME TABLE user_table to new_table_name");
@DeleteColumn:删除数据表中的列
database.execSQL("ALTER TABLE user_table ADD COLUMN job TEXT");
@RenameColumn:重命名数据表中的列
database.execSQL("ALTER TABLE user_table RENAME COLUMN job TO user_job");

迁移

在 Room 中使用 Migration 迁移工具 升级数据库步骤 :

如果不想提供迁移策略,直接进行破坏性升级(不保留之前的数据),可以直接使用 fallbackToDestructiveMigration()

  • 更新数据模型 :
    如果要 更改数据库的结构 , 更新 Entity 实体类 , 修改实体类就是修改数据库表结构 ; 修改 Dao 数据库访问接口对象 , 包括添加 / 删除 / 修改 表 / 列 / 索引 ;
  • 创建迁移类 :
    创建一个用于执行数据库迁移的 迁移类 Migration , Migration 迁移类应 实现 Room 的 Migration 接口 , 并 定义数据库从旧版本迁移到新版本的操作 ;
  • 指定迁移规则 :
    在 Room 数据库的构建器中 , 使用 addMigrations 方法指定迁移规则 , 该方法接受一组 Migration 迁移对象 , 每个 Migration 迁移对象 代表一个数据库版本之间的迁移操作 ;
  • 执行迁移 :
    当应用程序启动并访问数据库时,Room 将自动检测数据库版本并执行适当的迁移操作 , 应用程序可以无缝地将旧版本的数据库迁移到新版本,而不会丢失现有的数据。
自动升级

exportSchema必须设置为true(默认为true),否则会出现如下报错
Cannot create auto migrations when export schema is OFF.
首先需要在@Database注解中增加autoMigrations

@Database(entities = {User.class, Book.class}, version = 3,exportSchema = true,autoMigrations = @AutoMigration(from = 2,to = 3,spec = UserRoomDatabase.TestAutoMigration.class))

如果 Room 发现迁移过程中有歧义,并且在未提供更多信息的时候无法制定确切的自迁移方案,在编译期间就会发生错误,这时开发者需要提供一个 AutoMigrationSpec 的实现。多数情况下,自迁移发生错误都是由下列的原因造成的。

  • 删除或者重命名数据表名
  • 删除或者重命名数据表的列名
    @RenameColumn(tableName = "user_table", fromColumnName = "job", toColumnName = "user_job")
    static class TestAutoMigration implements AutoMigrationSpec { }
手动升级

//修改version = 2
@Database(entities = {User.class, Book.class}, version = 2,exportSchema = true)
创建具体的版本迁移策略

    //添加字段 具体的版本迁移策略
    public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            //添加字段
//            database.execSQL("ALTER TABLE user_table ADD COLUMN job TEXT NOT NULL DEFAULT '民工'");
            database.execSQL("ALTER TABLE user_table ADD COLUMN job TEXT");
//            database.execSQL("ALTER TABLE user_table RENAME COLUMN job TO user_job");
        }
    };



    //单例创建database
    static UserRoomDatabase getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (UserRoomDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(
                            context.getApplicationContext(),
                            UserRoomDatabase.class, DATABASE_NAME)
                            .addMigrations(MIGRATION_1_2)添加完了migration后,根据Room.builder把我们版本更新的信息add进去
                            .build();
                }
            }
        }
        return INSTANCE;
    }

补充

exportSchema设置为 true后,会在指定路径(app的build.gradle里设置的)下生成一个json文件,里面有不同版本的表的信息。

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值