Google 官方数据库框架Room使用教程

news2024/9/19 11:03:22

        Room 是 Google 提供的官方 ORM 框架,用于处理 Android 应用中的 SQLite 数据库操作。它是 Android Jetpack 的一部分,具有编译时检查、数据持久化的简化操作以及与 LiveData 和 RxJava 的良好集成。

以下是 Room 的详细使用教程,结合rxjava,并将其封装在 DatabaseHelper 中进行管理,同时处理数据库升级。

1. 添加依赖

首先,在 build.gradle 文件中添加 Room 和 RxJava 的依赖:

dependencies {
    // Room 依赖
    implementation "androidx.room:room-runtime:2.5.0"
    kapt "androidx.room:room-compiler:2.5.0" // 如果使用 Kotlin

    // RxJava 依赖
    implementation 'io.reactivex.rxjava3:rxjava:3.1.0'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'

    // Room 支持 RxJava
    implementation "androidx.room:room-rxjava3:2.5.0"
}

2. 创建实体类

Room 使用实体类来表示数据库中的表。每个实体类都对应一个数据库表,类的每个字段对应数据库表中的列。

@Entity(tableName = "users")
public class User {
    @PrimaryKey(autoGenerate = true)
    private int id;

    private String name;
    private int age;

    // Getters 和 Setters
}
重要注解:
  • @Entity:声明一个实体类,并指定表名。
  • @PrimaryKey:指定主键,autoGenerate = true 表示主键自动增长。
  • @ColumnInfo:用于指定列的名称(可选)。

3. 创建 DAO(数据访问对象)接口并集成 RxJava

DAO 是用来定义访问数据库的方法的接口。每个 DAO 都是一个接口,里面包含了数据库的查询、插入、删除和更新方法。

@Dao
public interface UserDao {

    // 查询所有用户,返回 Flowable 以便数据发生变化时自动通知观察者
    @Query("SELECT * FROM users")
    Flowable<List<User>> getAllUsers();

    // 根据 ID 获取用户
    @Query("SELECT * FROM users WHERE id = :userId")
    Single<User> getUserById(int userId);


    // 插入用户,使用 Completable 来处理异步插入操作
    @Insert
    Completable insertUser(User user);

    // 更新用户信息
    @Update
    Completable updateUser(User user);

    // 删除单个用户
    @Delete
    Completable deleteUser(User user);

    // 删除所有用户
    @Query("DELETE FROM users")
    Completable deleteAllUsers();
}
重要注解:
  • @Dao:定义 DAO 类。
  • @Query:用于定义 SQL 查询。
  • @Insert:用于插入数据。
  • @Update:用于更新数据。
  • @Delete:用于删除数据。

4. 创建 RoomDatabase 类

RoomDatabase 类是用于创建数据库并关联 DAO 的抽象类。它是 Room 框架的核心部分。

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
}
重要注解:
  • @Database:用于指定实体类和数据库版本。
  • RoomDatabase:通过继承该类,创建数据库实例。

5.封装 DatabaseHelper

将 Room 封装成一个简单易用的 DatabaseHelper,我们可以通过创建一个单例类来管理 Room 数据库的实例和 DAO 的操作。这样做可以避免在多个地方重复初始化数据库,同时也能简化对 DAO 的调用。

public class DatabaseHelper {

    private static DatabaseHelper instance;
    private final AppDatabase database;

    private DatabaseHelper(Context context) {
        database = Room.databaseBuilder(context.getApplicationContext(),
                AppDatabase.class, "my_database")
               // .fallbackToDestructiveMigration()// 如果没有迁移策略,销毁并重新创建
                .build();
    }

    public static synchronized DatabaseHelper getInstance(Context context) {
        if (instance == null) {
            instance = new DatabaseHelper(context);
        }
        return instance;
    }

    public UserDao getUserDao() {
        return database.userDao();
    }

    // 插入用户数据,返回 Completable
    public Completable insertUser(User user) {
        return getUserDao().insertUser(user)
                .subscribeOn(Schedulers.io())  // 在 IO 线程执行
                .observeOn(AndroidSchedulers.mainThread());  // 在主线程观察
    }

    // 查询所有用户,返回 Flowable,数据变更时通知观察者
    public Flowable<List<User>> getAllUsers() {
        return getUserDao().getAllUsers()
                .subscribeOn(Schedulers.io())  // 在 IO 线程查询
                .observeOn(AndroidSchedulers.mainThread());  // 在主线程观察
    }

    // 删除所有用户,返回 Completable
    public Completable deleteAllUsers() {
        return getUserDao().deleteAllUsers()
                .subscribeOn(Schedulers.io())  // 在 IO 线程执行
                .observeOn(AndroidSchedulers.mainThread());  // 在主线程观察
    }

}

注意:Room 数据库每次数据库结构发生变化(如添加、删除或修改表或字段)时更新数据库版本,并且需要定义迁移策略来确保数据的正确迁移,如果没有提供迁移策略,Room 会抛出异常。fallbackToDestructiveMigration ()的作用是在没有可用的迁移策略时,Room 直接删除旧的数据库文件,并重新创建一个新的数据库(包含新版本的数据库结构),但是 所有的旧数据都会丢失

6. 数据库迁移

如果你对数据库结构进行修改(如添加字段),需要执行数据库迁移,避免数据丢失。Room 提供了 Migration 类用于管理数据库版本的升级。如当新增加一个Book表:

6.1. 创建新的实体类 Book

import androidx.room.Entity;
import androidx.room.PrimaryKey;

@Entity(tableName = "books")
public class Book {
    @PrimaryKey(autoGenerate = true)
    public int id;

    public String title;
    public String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    // Getters and Setters (根据需要生成)
}

6.2. 创建 BookDao 接口

import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import androidx.room.Delete;

import java.util.List;

import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Single;

@Dao
public interface BookDao {
    // 插入书籍
    @Insert
    Completable insertBook(Book book);

    // 获取所有书籍
    @Query("SELECT * FROM books")
    Flowable<List<Book>> getAllBooks();

    // 根据 ID 获取书籍
    @Query("SELECT * FROM books WHERE id = :bookId")
    Single<Book> getBookById(int bookId);

    // 更新书籍
    @Update
    Completable updateBook(Book book);

    // 删除书籍
    @Delete
    Completable deleteBook(Book book);
}

6.3.更新 AppDatabase 类并添加迁移逻辑

import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;

@Database(entities = {User.class, Book.class}, version = 2) // 更新版本号
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    public abstract BookDao bookDao();// 添加 BookDao

    private static volatile AppDatabase INSTANCE;

    public static AppDatabase getInstance(Context context) {
        if (INSTANCE == null) {
            synchronized (AppDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, "my_database")
                            .addMigrations(MIGRATION_1_2)  // 添加迁移策略
                            .build();
                }
            }
        }
        return INSTANCE;
    }

    // 定义迁移策略:从版本 1 升级到版本 2
    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            // 创建新表 Book
            database.execSQL("CREATE TABLE IF NOT EXISTS `books` (" +
                    "`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
                    "`title` TEXT, " +
                    "`author` TEXT)");
        }
    };
}

7、多次迁移情况

如果你有多个版本的数据库更新,例如从版本 1 升级到 2,之后再升级到 3,每次升级都需要定义相应的迁移策略。

static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        // 例如,在版本 3 中新增字段
        database.execSQL("ALTER TABLE users ADD COLUMN last_login INTEGER");
    }
};

// 添加多个迁移
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "user_database")
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3)
    .build();

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

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

相关文章

硬件(驱动开发概念)

驱动程序开发 裸机驱动&#xff08;无操作系统&#xff09; Linux驱动 以计算机技术为基础&#xff0c;在软件和硬件层间可以被剪裁的专业硬件计算机系统 SOC&#xff1a;片上系统 Kernel&#xff1a;内核 x86 &#xff08;CISC:complex instruction set computer 复杂指令…

IEEE Electronic Library(IEL)数据库文献检索下载介绍及个人获取IEEE文献途径

一、数据库介绍 IEEE&#xff08;The Institute of Electrical and Electronics Engineers&#xff0c;电气电子工程师学会&#xff09;是目前全球最大的非营利性专业技术学会&#xff0c;在全球160多个国家拥有超过45万名会员。IEEE在电气电子、计算机、半导体、通讯、电力能…

24年蓝桥杯及攻防世界赛题-MISC-3

21 reverseMe 复制图片&#xff0c;在线ocr识别&#xff0c;https://ocr.wdku.net/&#xff0c;都不费眼睛。 22 misc_pic_again ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc/zsteg] └─$ zsteg misc_pic_again.png imagedata … text: “$$KaTeX parse error: Undefined…

方法:批量提取PPT幻灯片中图片

处理包含大量图片的PPT&#xff08;PowerPoint&#xff09;幻灯片已成为许多专业人士的日常任务之一。然而&#xff0c;手动从每张幻灯片中逐一提取图片不仅耗时耗力&#xff0c;还容易出错。为了提升工作效率&#xff0c;减少重复劳动&#xff0c;探索并实现一种高效批量提取P…

STM32F407单片机开发入门(二)STM32F407VET6单片机详解

文章目录 一.概要二.单片机型号命名规则三.STM32F407系统架构四.STM32F40VET6单片机启动流程五.STM32F40VET6单片机主要外设资源六.开发过程中查看芯片数据手册的必要性1.单片机外设资源情况2.STM32F407单片机内部框图3.STM32F407单片机管脚图4.STM32F407单片机每个管脚功能5.单…

球类目标检测系统源码分享

球类目标检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

IOS 26 实现歌单详情(UITableView)列表 ③

歌单详情完整效果 歌单列表分组头部效果 本节是在文章 IOS 25 实现歌单详情&#xff08;UITableView&#xff09;列表② 的基础上&#xff0c;实现歌单列表分组头部View。当歌单列表滑动头部View至顶部时&#xff0c;头部View不会因列表滑动而消失&#xff0c;会一直显示在顶部…

2024.9.18

1.已知网址www.hqyj.com截取出网址的每一个部分 菜单栏中 ----> 虚拟机 -----> 设置 -----> 网络适配器 选择桥接模式 菜单栏中 ----> 编辑 -----> 虚拟网络编辑器 更改设置 将桥接改成自动 如果桥接连不上网 尝试还原默认设置后&#xff0c;在重新连接桥接…

微信小程序的学生选课系统--论文源码调试讲解

第二章 开发技术介绍 此次管理系统的关键技术和架构由B/S结构、java和mysql数据库&#xff0c;是本系统的关键开发技术&#xff0c;对系统的整体、数据库、功能模块、系统页面以及系统程序等设计进行了详细的研究与规划。 2.1 系统开发平台 在该在线微信小程序的学生选课系统…

动手学习RAG: 大模型向量模型微调 intfloat/e5-mistral-7b-instruct

动手学习RAG: 向量模型动手学习RAG: moka-ai/m3e 模型微调deepspeed与对比学习动手学习RAG&#xff1a;rerank模型微调实践 bge-reranker-v2-m3动手学习RAG&#xff1a;迟交互模型colbert微调实践 bge-m3动手学习RAG: 大模型向量模型微调 intfloat/e5-mistral-7b-instruct动手学…

JavaScript高级——内存溢出和内存泄漏

1、闭包的缺点与解决方法 &#xff08;1&#xff09;缺点&#xff1a;函数执行完后&#xff0c;函数内的局部变量没有释放&#xff0c;占用内存时间会变长。 容易造成内存泄漏。 &#xff08;2&#xff09;解决&#xff1a;能不用闭包就不用。 及时释放。 2、内存溢出 ① 一…

Linux进阶 查看系统进程

操作系统中进程的生命周期是: 创建进程,(服务启动或软件的启动)进行运行状态进程等待状态进行唤醒进程结束一般主要关注是进行中间的三种状态,三种状态之间装换关系如下: 1、就绪状态:表示进程已经做好了运行的准备状态,只要获得内存空间,就可以立即执行。 2、阻塞状态:…

Maya---机械模型制作

材质效果&#xff08;4&#xff09;_哔哩哔哩_bilibili 三角面 四边面 多边面 *游戏允许出现三角面和四边面 游戏中一般是低模&#xff08;几千个面&#xff09; 动漫及影视是高模 机械由单独零件组合而成&#xff0c;需独立制作 低面模型到高面模型 卡线是为了将模型保…

电脑怎么设置开机密码?3个方法迅速搞定!

电脑已经成为了我们日常办公与学习的重要工具&#xff0c;其中保存有很多重要且需保密的资料&#xff0c;为电脑设置开机密码则是保护资料安全的第一步。那么&#xff0c;电脑怎么设置开机密码呢&#xff1f;今天&#xff0c;小编就为大家介绍3个设置电脑开机密码的方法&#x…

深度学习对抗海洋赤潮危机!浙大GIS实验室提出ChloroFormer模型,可提前预警海洋藻类爆发

2014 年 8 月&#xff0c;美国俄亥俄州托莱多市超 50 万名居民突然收到市政府的一则紧急通知——不得擅自饮用自来水&#xff01; 水是人类生存的基本供给&#xff0c;此通告关系重大&#xff0c;发出后也引起了不小的恐慌。究其原因&#xff0c;其实是美国伊利湖爆发了大规模…

油烟机制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

油烟机制造5G智能工厂物联数字孪生平台&#xff0c;是智能制造与信息技术的深度融合产物。数字孪生工业互联平台通过部署在工厂各个环节的传感器和设备&#xff0c;实时采集、分析和处理生产过程中的海量数据&#xff0c;构建出高度逼真的数字孪生模型。这一模型不仅能够真实反…

基于树莓派ubuntu20.04的ros-noetic小车

目录 一、小车的架构 1.1 总体的概述 1.2 驱动系统 1.3 控制系统 二、驱动系统开发 2.1 PC端Ubuntu20.04安装 2.2 树莓派Ubuntu20.04安装 2.3 PC端虚拟机设置静态IP 2.4 树莓派设置静态IP 2.5 树莓派启动ssh进行远程开发 2.5 arduino ide 开发环境搭建 2.5.1 PC…

深入探索Docker核心原理:从Libcontainer到runC的演化与实现

随着容器技术的发展&#xff0c;Docker从早期的Libcontainer逐步演化到runC&#xff0c;推动了容器运行时的标准化进程。Libcontainer是Docker容器的核心管理工具&#xff0c;而runC则在此基础上发展成为符合OCI&#xff08;Open Container Initiative&#xff09;标准的轻量级…

Vue常用PC端和移动端组件库、Element UI的基本使用(完整引入和按需引入)

目录 1. Vue常用PC端和移动端组件库2. Element UI的基本使用2.1 完整引入2.2 按需引入 1. Vue常用PC端和移动端组件库 提供常用的布局、按钮、输入框、下拉框等UI布局&#xff0c;以组件的形式提供。使用这些组件&#xff0c;结构、样式、交互就都有了 移动端常用UI组件库 Van…

windows10 修改默认输入法

右键桌面&#xff0c;选择个性化 左侧搜索 语言 选择编辑语言和键盘选项 点击键盘 默认替代输入法 选择你想要设置的。重启电脑。如下图