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"

...

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

相关推荐
没有了遇见41 分钟前
Kotlin高级用法之<扩展函数/属性>
android·kotlin
安卓开发者43 分钟前
Android中使用RxJava实现网络请求与缓存策略
android·网络·rxjava
AI 嗯啦1 小时前
SQL详细语法教程(七)核心优化
数据库·人工智能·sql
2501_915921432 小时前
iOS 应用上架多环境实战,Windows、Linux 与 Mac 的不同路径
android·ios·小程序·https·uni-app·iphone·webview
ClouGence2 小时前
三步搞定!GaussDB 实时数据入仓
数据库·后端
wstcl3 小时前
安卓app、微信小程序等访问多个api时等待提示调用与关闭问题
android·微信小程序·webapi
鼠鼠我捏,要死了捏3 小时前
生产环境MongoDB分片策略优化与故障排查实战经验分享
数据库·mongodb·分片
KaiwuDB4 小时前
KWDB 分布式架构探究——数据分布与特性
数据库·分布式
笨蛋不要掉眼泪4 小时前
Spring Boot集成腾讯云人脸识别实现智能小区门禁系统
java·数据库·spring boot
louisgeek5 小时前
Android Studio 打印中文乱码
android