Android Room 数据库自动升级与迁移策略

news2024/9/19 9:05:35

前序

在 Android 应用开发中,Room 是 Google 提供的一个轻量级数据库框架,用于简化与 SQLite 的交互。在应用的迭代过程中,数据库的结构不可避免地会发生变化,因此,我们需要为数据库升级、降级以及数据迁移制定一套合适的策略。

本文将介绍 Room 数据库升级的几种场景和常见的处理方法,包括手动迁移和自动迁移的策略。

何时需要升级数据库版本号?

以下几种情况会导致数据库结构的变更,因此必须升级数据库版本号,并处理相应的迁移逻辑:

  1. 新增或删除表:当我们向数据库中添加或删除一张表时,必须升级版本号,并实现相应的迁移处理逻辑,以确保数据的一致性。

  2. 新增、删除或修改字段:当对表中的字段进行操作时,例如新增一个列、删除或重命名列,必须升级数据库版本号,同时处理好字段的迁移或初始化逻辑。

  3. 修改索引或约束:如果为某些字段添加索引,或者对字段的约束(如非空、唯一等)进行修改,同样需要升级版本号。

Room 数据库迁移策略

Room 提供了多种处理数据库迁移的方式,开发者可以根据项目需求选择合适的迁移策略:

1. fallbackToDestructiveMigration 删除数据库并重建

如果应用中的数据不重要,或者我们允许用户丢失数据库中的所有数据,可以使用 fallbackToDestructiveMigration 方法,该方法会在版本号发生变化时直接删除数据库并重建。

private static AppDatabase create(final Context context) {
    return Room.databaseBuilder(
            context,
            AppDatabase.class,
            "AppDatabase.db")
        .fallbackToDestructiveMigration() // 自动删除并重建数据库
        .build();
}

注意:使用这种方式,所有的旧数据都会被删除,因此适合那些对数据持久性要求不高的场景。

2. addMigrations 自定义迁移逻辑

当需要保留用户数据时,可以通过自定义 Migration 来处理数据库结构变更。例如,给 user 表新增一个 testId 字段:

public static final Migration MIGRATION_2_3 = new Migration(2, 3) { 
    @Override 
    public void migrate(@NonNull SupportSQLiteDatabase database) { 
        // 添加新字段并为其设置默认值
        database.execSQL("ALTER TABLE user ADD testId INTEGER DEFAULT 0 NOT NULL");
    } 
};

在数据库的 Room 实例构建时,将这个迁移添加到数据库构建器中:

private static AppDatabase create(final Context context) {
    return Room.databaseBuilder(
            context,
            AppDatabase.class,
            "AppDatabase.db")
        .addMigrations(MIGRATION_2_3) // 自定义的迁移
        .build();
}

优点:这种方式可以确保在数据库结构变更时,用户的数据不会丢失,数据迁移可以按照开发者定义的逻辑进行。

3. Room 数据库自动迁移

从 Room 2.4 版本开始,支持自动迁移功能,能够根据数据库的 schema 文件自动生成迁移逻辑,简化了跨版本的升级工作。在自动迁移中,Room 会自动处理字段的增加和删除,开发者只需配置好数据库的 schemaLocation

步骤一:配置 room.schemaLocation

app/build.gradle 文件中配置注解处理器的参数,以便在编译时生成数据库的 schema 文件:

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
            }
        }
    }
}

编译时会在配置的目录下生成数据库版本号对应的 json 文件 — 主要信息为数据库相关信息、相关表信息,自动升级会根据这些信息生成 Migration。升级方式类似于手动升级的方式。
所有的使用的版本号对应的 json 文件都不能缺少,否则对应版本的升级会出问题,若中途进行的数据库的自动化升级迁移,可考虑回退版本,编译成对应的 json 拷贝过来。

    app 
    ├── build 
    │   ├── libs 
    │   ├── release 
    │   └── schemas 
    │       └── database.AppDatabase.json 
    │       └── 2.json 
    │       └──.json 
步骤二:配置自动迁移

Room 允许开发者定义跨版本的自动迁移,例如从 version 1 直接升级到 version 4

@Database(
    entities = {User.class}, 
    version = 4,
    autoMigrations = {
        @AutoMigration(from = 1, to = 2),
        @AutoMigration(from = 2, to = 3),
        @AutoMigration(from = 3, to = 4),
        @AutoMigration(from = 1, to = 4)
    }
)
public abstract class AppDatabase extends RoomDatabase {
}

注意:在自动迁移中,字段的新增需要设置 defaultValue,否则会报错:

@ColumnInfo(defaultValue = "0") 
public int testId;

4. Room 跨版本升级与降级

Room 也支持顺序或跨版本的数据库升级。假设用户下载的是最新版本的应用(版本号为 4),而数据库版本从未升级(还停留在 version 1),Room 会自动依次执行从 version 1version 4 的所有迁移。

如果我们希望加快迁移速度,可以定义一个从 version 1 直接到 version 4 的迁移逻辑,并通过 addMigrations 方法添加:

public static final Migration MIGRATION_1_4 = new Migration(1, 4) { 
    @Override 
    public void migrate(@NonNull SupportSQLiteDatabase database) { 
        // 自定义跨版本迁移逻辑
        database.execSQL("ALTER TABLE user ADD COLUMN testId INTEGER DDEDAQEFAULT 0 NOT NULL");
        database.execSQL("ALTER TABLE user ADD COLUMN test INTEGER DEDAQ 0 NOT NULL");
    } 
};

添加迁移到 Room 实例:

db = Room.databaseBuilder(MyApplication.getInstance(), AppDatabase.class, "AppDatabase.db")
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4)
    .fallbackToDestructiveMigration() // 防止没有匹配到的迁移时崩溃
    .build();

通过这种方式,用户可以直接从 version 1 升级到 version 4,避免了逐个版本的迁移。

总结

在 Android 应用的开发中,数据库的升级与迁移是不可避免的工作。Room 提供了灵活的数据库迁移机制,可以通过手动定义迁移、自动生成迁移,或在必要时重建数据库。开发者应根据应用的实际需求选择合适的升级方案,以确保用户数据的完整性和系统的稳定性。

  • 自动迁移:适用于简单字段的增加、删除等结构变化。
  • 自定义迁移:适合复杂的数据库操作,能够灵活应对各种数据库结构调整。
  • 重建数据库:适用于数据不重要或者允许丢失数据的场景。

通过合理的迁移策略,确保数据库的稳定升级,是提高应用质量的重要一环。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145955.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试 - 报数问题 - 约瑟夫环(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(E卷D卷A卷B卷C卷)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加…

python画图|在3D图上画2D直方图(作图平面移动)

前期我们已经学习过2D和3D的直方图绘制: 二维常规直方图绘制:python画图|水平直方图绘制_绘制水平直方图-CSDN博客 二维极坐标直方图绘制:python画图|极坐标中画直方图_ax1.plot()怎么画直方图-CSDN博客 三维直方图绘制:python…

Spring考点总结

01.Spring框架的基本理解 关键字:核心思想IOC\AOP\作用(解耦、简化),简单描述框架组成 Spring框架是一款轻量级的开发框架,核心思想是IOC(控制反转)和AOP(面向切面编程), 为Java应用程序开发…

使用Addressables+SpriteAtlas打包产生冗余

1)使用AddressablesSpriteAtlas打包产生冗余 2)使用SBP打AssetBundle脚本引用丢失 3)Unity构建后处理(IPostprocessBuildWithReport等接口)抛出异常后,构建不会停止 4)Unity 2022.3.0版本使用Oc…

基于YOLOv8的RTSP视频流实时目标检测与告警系统设计与实现(超详细)

前言 在训练模型完成后,想把模型应用起来,比如模型可以部署到项目中,实时接收RTSP视频流进行识别检测,一旦达到自己所设置的置信度阈值(例如大于0.5),系统就会实时把报警信息发送给服务端&…

基于web的工作管理系统设计与实现

博主介绍:专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

01 Vim 编辑器的简单使用

目前在类liunx系统上,我们使用比较多的是 vim 编辑器。vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计。 文章目录 1 vim介绍2 vim 三种模式3 常用快捷键一般模式操作:切换模式操作:增删…

体感魂斗罗(一)

文章目录 体感魂斗罗实现步骤设备读取摄像头视频流使用电脑摄像头读取局域网内手机摄像头效果示意IP摄像头底部工具栏 体感魂斗罗实现步骤 目前想到的有如下步骤 读取摄像头视频流图像检测人体关键点关键点转换为人体姿势固定姿势转换键盘键位 设备 摄像头(可用手…

[数据集][目标检测]文本表格检测数据集VOC+YOLO格式6688张5类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):6688 标注数量(xml文件个数):6688 标注数量(txt文件个数):6688 标注…

上半年亏损扩大/百亿资产重组终止,路畅科技如何“脱困”?

在智能网联汽车市场形势一片大好的前提下,路畅科技上半年的营收却出现了下滑,并且亏损也进一步扩大。 2024年半年度报告显示,路畅科技营业收入1.35亿元,同比下滑7.83%;实现归属上市公司股东的净利润为亏损2491.99万元…

【oj刷题】二分查找篇:二分查找算法的原理和应用场景

前言: 二分查找算法,又称折半查找算法,是一种在有序数组中查找特定元素的高效查找方法。它通过将搜索区间不断缩小一半,从而在对数时间内找到目标元素。二分查找是基于分治策略的一种典型应用,能够高效的处理许多问题&…

软考高级:嵌入式系统调度算法 AI 解读

嵌入式系统中的调度算法用于管理任务的执行顺序,确保系统资源能够有效分配。以下是几种常见的调度算法的通俗讲解。 生活化例子 想象你是一位超市收银员,有很多顾客排队,每位顾客都可以看作一个任务,收银台就是你的处理器。你需…

1.1 软件测试 + AI

欢迎大家订阅【软件测试】学习专栏,开启你的软件测试学习之旅! 文章目录 前言一、软件测试二、人工智能的引入 前言 人工智能的引入为软件测试带来了巨大的变革,不仅提升了测试效率和准确性,也为软件质量的保障提供了新的手段。通…

通信工程学习:什么是ONT光网络终端

ONT:光网络终端 ONT(Optical Network Terminal,光网络终端)是光纤接入网络(FTTH)中的关键设备,用于将光纤信号转换为电信号或将电信号转换为光信号,以实现用户设备与光纤网络的连接。…

华为OD机试 - 返回矩阵中非1的元素个数 - 广度优先搜索BFS(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,…

最长连续子序列 - 华为OD统一考试(E卷)

OD统一考试(E卷) 分值: 100分 题解: Java / Python / C 2024华为OD机试(E卷D卷C卷)最新题库【超值优惠】Java/Python/C合集 题目描述 有N个正整数组成的一个序列。给定整数sum,求长度最长的连续…

WIFI路由器的套杆天线简谈

❝本次推文简单介绍下WIFI路由器的套杆天线。 路由器天线 路由器在这个万物互联的时代,想必大家对其都不陌生。随着科技的发展,常用的路由器上的天线也越来越多,那么问题来了:天线越多,信号越好吗?路由器…

前端mock了所有……

目录 一、背景描述 二、开发流程 1.引入Mock 2.创建文件 3.需求描述 4.Mock实现 三、总结 一、背景描述 前提: 事情是这样的,老板想要我们写一个demo拿去路演/拉项目,有一些数据,希望前端接一下,写几个表格&a…

Linux进程间通信——探索共享内存—— 剖析原理, 学习接口应用

前言:本节内容主要讲解进程间通信的, systemV版本下的共享内存。 共享内存,顾名思义, 其实就是一块内存, 它不同于管道是一个文件。 所以它的传输速度是很快的。 因为管道是文件,有缓冲区, 而共…

Day99 代码随想录打卡|动态规划篇--- 01背包问题

题目(卡玛网T46): 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等&am…