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"

...

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

相关推荐
Majoy222 分钟前
HBase
大数据·数据库·hbase
夜光小兔纸1 小时前
oracle查询出表中某几个字段值不唯一的数据
数据库·sql·oracle
deadknight93 小时前
Oracle密码过期处理方式
数据库·oracle
Ljubim.te3 小时前
数据库第01讲章节测验(选项顺序可能不同)
数据库
吱吱喔喔3 小时前
数据分表和分库原理
数据库·分表·分库
快乐非自愿3 小时前
KES数据库实践指南:探索KES数据库的事务隔离级别
数据库·oracle
一只fish3 小时前
Oracle的RECYCLEBIN回收站:轻松恢复误删对象
数据库·oracle
codemami3 小时前
oracle中的nocache的用法和例子
oracle
weixin_440401693 小时前
分布式锁——基于Redis分布式锁
java·数据库·spring boot·redis·分布式
TOR-NADO3 小时前
数据库概念题总结
数据库·oracle