Room 数据库思维导图
中心主题: Room (Android 持久化库)
核心概念
- 是什么?
- 一个在 Android 应用中创建本地数据库的官方库。
- 位于 Android Jetpack 组件包中。
- 提供了一个抽象层,在 SQLite 之上,让数据库访问更简单、更健壮。
- 为什么用?
- 编译时检查: 通过注解在编译时捕获 SQL 查询错误。
- 简化 DAO: 提供便捷的方法来查询、插入、更新和删除数据。
- LiveData 集成: 轻松实现数据变更的自动 UI 更新。
- RxJava, Flow, Guava 支持: 可以与流行的响应式编程库无缝集成。
- 事务支持: 确保数据操作的原子性。
三大核心组件
- 1. Database (数据库)
- 作用: 数据库的主要入口点,持有数据库连接。
- 关键特性:
- 必须是
abstract类。 - 使用
@Database注解。 - 包含一个或多个
DAO的抽象方法。 - 定义数据库版本号 (
version)。 - 可以列出包含的所有实体类 (
entities)。 - 可以定义数据库导出/导入时的回调 (
exportSchema)。
- 必须是
- 2. Entity (实体)
- 作用: 代表数据库中的一张表。
- 关键特性:
- 使用
@Entity注解一个数据类。 - 主键: 必须定义一个主键,使用
@PrimaryKey注解。autoGenerate = true: 可选,让 Room 自动生成主键值。
- 索引: 使用
@Index注解为列创建索引,提高查询速度。 - 关系: 使用
@ForeignKey注解定义表与表之间的关系。 - 列名映射: 使用
@ColumnInfo注解自定义列名。 - 忽略字段: 使用
@Ignore注解标记不需要存入数据库的字段。
- 使用
- 3. DAO (Data Access Object - 数据访问对象)
- 作用: 定义访问数据库的方法(增删改查)。
- 关键特性:
- 是一个接口或抽象类。
- 使用
@Dao注解。 - 方法类型:
- 查询:
@Query("SELECT ...")- 执行 SQL 查询。 - 插入:
@Insert- 插入数据,可以返回新行的 ID。 - 更新:
@Update- 更新已存在的行,根据主键匹配。 - 删除:
@Delete- 删除行,根据主键匹配。
- 查询:
- 事务: 使用
@Transaction注解确保一组操作的原子性。
工作流程
-
第一步: 添加依赖
- 在
build.gradle(Module: app) 文件中添加 Room 依赖。 -
// Kotlin implementation "androidx.room:room-runtime:2.6.1" kapt "androidx.room:room-compiler:2.6.1" // Kotlin 扩展和协程支持 implementation "androidx.room:room-ktx:2.6.1"
- 在
-
第二步: 定义实体类
- 创建数据类,并用
@Entity注解。 -
@Entity data class User( @PrimaryKey val id: Int, val name: String, val age: Int )
- 创建数据类,并用
-
第三步: 创建 DAO 接口
-
定义接口,并用
@Dao注解。 -
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAllUsers(): List<User> @Insert suspend fun insertUser(user: User) }
-
-
第四步: 创建 Database 类
- 创建抽象类,并用
@Database注解。 - 包含实体和 DAO 的引用。
-
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
- 创建抽象类,并用
-
第五步: 在应用中获取数据库实例
- 使用
Room.databaseBuilder()创建单例实例。 - 注意: 避免在主线程中操作数据库。
-
val db = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "database-name" ).build()
- 使用
高级特性
- 1. 类型转换
- 作用: 将自定义数据类型与数据库支持的类型进行转换。
- 实现: 创建一个继承自
TypeConverter的类,并定义@TypeConverter注解的方法。 - 场景: 将
Date或List<String>存储为TEXT。
- 2. 数据库迁移
- 作用: 当数据库结构(如实体类)发生变化时,更新用户设备上的现有数据库。
- 实现: 在
RoomDatabase.Builder中使用addMigrations()方法。 - 关键类:
Migration,它包含startVersion,endVersion和一个migrate()方法,用于手动编写 SQL 语句来更新数据库架构。
- 3. 测试
- Room 测试支持: 提供一个
Room.inMemoryDatabaseBuilder(),用于在内存中创建数据库,非常适合单元测试。 - 测试数据库: 确保你的 DAO 查询和操作按预期工作。
- Room 测试支持: 提供一个
- 4. 响应式编程
- Flow: DAO 方法可以直接返回
Flow<T>,当数据库中的数据发生变化时,会自动发出新数据流。 - LiveData: DAO 方法可以返回
LiveData<T>,这是 Android 推荐的用于 UI 观察的方式,能自动处理生命周期。 - RxJava: DAO 方法可以返回
Single,Maybe,Flowable等 RxJava 类型。
- Flow: DAO 方法可以直接返回
最佳实践
- 单例模式:
AppDatabase应该是整个应用的单例,以避免打开多个数据库连接。 - 不要在主线程操作: 所有数据库操作都应在后台线程执行,可以使用协程、RxJava 或
Executor。 - 使用 Kotlin 协程: 结合
room-ktx库,可以使用suspend函数让异步操作代码更简洁。 - 为查询使用参数化查询: 始终使用 作为占位符(如
name)来防止 SQL 注入,而不是手动拼接字符串。 - 定义清晰的 DAO: 每个 DAO 应该专注于一个特定功能或实体,使代码更易于维护。
- 导出架构: 在
@Database中设置exportSchema = true,并将schemaLocation指定到一个目录,这有助于版本控制和迁移。
