Android Room数据库使用介绍

1.简介


Room是Google提供的Android架构组件之一,旨在简化数据库操作。它是SQLite的一个抽象层,提供了更易用和安全的API。

Room的总体架构:

2.Room数据库的基础概念


Entity

Entity是Room中的数据表,每个Entity类对应一个SQLite表。

DAO (Data Access Object)

DAO是用于访问数据库的方法接口,定义了与数据库交互的操作。

Database

Database是Room数据库的抽象类,持有数据库并作为数据访问的主要入口点。

3.Room数据库的配置


添加依赖

在build.gradle文件中添加Room的依赖项。

groovy 复制代码
dependencies {
    implementation "androidx.room:room-runtime:2.5.0"
    annotationProcessor "androidx.room:room-compiler:2.5.0"
    // 可选 - 支持Lifecycle的LiveData
    implementation "androidx.room:room-ktx:2.5.0"
}

定义Entity

kotlin 复制代码
// tableName 指定了数据库中对应的表名为 "users"。如果不指定,默认使用类名作为表名
@Entity(tableName = "users")
data class User(
    // 使用默认值 0,autoGenerate = true 表示自动生成主键
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0, 
    // 如果不使用 @ColumnInfo 注解,默认情况下 Room 将使用属性名作为数据库中的列名
    @ColumnInfo(name = "first_name")
    val firstName: String,
    @ColumnInfo(name = "last_name")
    val lastName: String
)

创建DAO

kotlin 复制代码
@Dao
interface UserDao {
    @Insert
    fun insert(user: User)
    //@Insert(onConflict = OnConflictStrategy.REPLACE):用于定义插入操作,并指定了替换策略为 OnConflictStrategy.REPLACE。这意味着如果插入的数据在数据库中已存在(根据主键判断),则旧数据会被新数据替换。
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(user: User)

    @Query("SELECT * FROM users WHERE id = :id")
    fun getUserById(id: Int): User?

    @Update
    fun update(user: User)

    @Delete
    fun delete(user: User)
}

tips: OnConflictStrategy.REPLACE:如果插入的数据在数据库中已存在(即主键冲突),则会替换原有的数据。

创建Database

kotlin 复制代码
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserRoomDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {
        @Volatile
        private var INSTANCE: ItemRoomDatabase? = null

        fun getDatabase(context: Context): UserRoomDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    UserRoomDatabase::class.java,
                    "user_database"
                )
                    .fallbackToDestructiveMigration()
                    .build()
                INSTANCE = instance
                instance
            }
        }
    }
}

tips:注意fallbackToDestructiveMigration() 一般在调试中使用,如果你修改了数据库表结构,而没有升级数据库通常程序再次运行会报错,使用fallbackToDestructiveMigration() 表示将老的数据库表结构和数据全部删除,使用新的结构,允许破坏性迁移,即销毁旧数据库并创建新数据库。

初始化数据库

kotlin 复制代码
val db: UserRoomDatabase by lazy { UserRoomDatabase.getDatabase(this) }

4.Room数据库的使用


插入数据

kotlin 复制代码
val user = User().apply {
    firstName = "John"
    lastName = "Doe"
}
db.userDao().insert(user)

查询数据

kotlin 复制代码
val user = db.userDao().getUserById(1)

更新数据

kotlin 复制代码
user.lastName = "Smith"
db.userDao().update(user)

删除数据

kotlin 复制代码
db.userDao().delete(user)

5.Room数据库的高级特性


使用LiveData和Flow

kotlin 复制代码
@Query("SELECT * FROM users")
LiveData<List<User>> getAllUsers();

@Query("SELECT * FROM users")
Flow<List<User>> getAllUsersFlow();

数据库迁移

kotlin 复制代码
@Database(entities = [User::class], version = 2, exportSchema = false)
abstract class UserRoomDatabase : RoomDatabase() {

    abstract fun userDao(): UserDao

    companion object {
        @Volatile
        private var INSTANCE: ItemRoomDatabase? = null
        //迁移代码 用于从版本 1 迁移到版本 2。
        val MIGRATION_1_2: Migration = object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                //为users表增加age属性
                database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER")
            }
        }

        fun getDatabase(context: Context): UserRoomDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    UserRoomDatabase::class.java,
                    "user_database"
                )
                    .addMigrations(AppDatabase.MIGRATION_1_2) //在此处添加
                    .build()
                INSTANCE = instance
                instance
            }
        }
    }
}

使用TypeConverters

kotlin 复制代码
@Database(entities = [User::class], version = 1)
@TypeConverters(Converters::class)
abstract class UserRoomDatabase: RoomDatabase() {
    abstract fun userDao(): UserDao
    ...
}

object Converters {
    @TypeConverter
    @JvmStatic
    fun fromTimestamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    @JvmStatic
    fun dateToTimestamp(date: Date?): Long? {
        return date?.time
    }
}

User 中增加 Date类型 createdAt属性

kotlin 复制代码
@Entity(tableName = "users")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val name: String,
    val createdAt: Date
)

说明:

  • 类型转换器 (Converters):使用 Room 持久化库时,有时需要在数据库存储和应用程序中的对象之间进行转换。例如,将 Date 对象存储为 Long 类型的时间戳或从时间戳恢复为 Date 对象,其他对象类型同理。
  • @TypeConverter 注解:用于标记类型转换器的方法,告诉 Room 如何在持久化过程中执行对象到数据库兼容格式之间的转换。
  • @Database 和 @TypeConverters 注解:用于在 UserRoomDatabase中指定数据库的配置,包括数据库版本号和要使用的类型转换器。

示例:

kotlin 复制代码
class Converters {

    //enum 类型
    @TypeConverter
    fun toDownloadStatus(value: String): DownloadStatus = enumValueOf(value)

    @TypeConverter
    fun fromDownloadStatus(status: DownloadStatus): String = status.name


    @TypeConverter
    fun fromHashMap(value: HashMap<Int, Int>): String {
        val gson = Gson()
        return gson.toJson(value)
    }

    @TypeConverter
    fun toHashMap(value: String): HashMap<Int, Int> {
        val gson = Gson()
        val type = object : TypeToken<HashMap<Int, Int>>() {}.type
        return gson.fromJson(value, type)
    }

    //自定义对象
    @TypeConverter
    fun fromDownloadException(downloadException: DownloadException?): String? {
        if (downloadException == null) {
            return null
        }
        return Gson().toJson(downloadException)
    }

    @TypeConverter
    fun toDownloadException(value: String?): DownloadException? {
        if (value == null) {
            return null
        }
        val type = object : TypeToken<DownloadException>() {}.type
        return Gson().fromJson(value, type)
    }
}

6. Room数据库的实践


线程管理

确保数据库操作在后台线程中完成,在主线程中操作数据库会报错。

kotlin 复制代码
Executors.newSingleThreadExecutor().execute {
    db.userDao().insert(user)
}

数据库性能优化

  • 使用批量插入和更新。
  • 使用索引提高查询性能。

处理大型数据集

使用分页库(Paging Library)处理大型数据集。

kotlin 复制代码
@Query("SELECT * FROM users ORDER BY id ASC")
fun getAllUsers(): PagingSource<Int, User>

使用分页库需要增加依赖

groovy 复制代码
implementation "androidx.paging:paging-runtime-ktx:$paging_version"

...

后面单独写篇文章介绍分页库使用,敬请期待...

相关推荐
guoruijun_2012_41 分钟前
fastadmin多个表crud连表操作步骤
android·java·开发语言
Winston Wood1 分钟前
一文了解Android中的AudioFlinger
android·音频
sj11637394034 分钟前
Kafka参数了解
数据库·分布式·kafka
日里安1 小时前
8. 基于 Redis 实现限流
数据库·redis·缓存
EasyCVR2 小时前
ISUP协议视频平台EasyCVR视频设备轨迹回放平台智慧农业视频远程监控管理方案
服务器·网络·数据库·音视频
Elastic 中国社区官方博客2 小时前
使用真实 Elasticsearch 进行更快的集成测试
大数据·运维·服务器·数据库·elasticsearch·搜索引擎·集成测试
B.-2 小时前
Flutter 应用在真机上调试的流程
android·flutter·ios·xcode·android-studio
有趣的杰克2 小时前
Flutter【04】高性能表单架构设计
android·flutter·dart
明月与玄武3 小时前
关于性能测试:数据库的 SQL 性能优化实战
数据库·sql·性能优化
PGCCC4 小时前
【PGCCC】Postgresql 存储设计
数据库·postgresql