JetPack系列(四)Room

如遇图片无法查看,请点击此链接

Room的使用

  • @Entity:表示数据中的表
  • @DAO:数据库操作对象
  • @Database数据库:必须是扩展RoomDatabase的抽象类。在注解中添加与数据库关联的数据表。包含使用@Dao注解标记的类和抽象方法
集成
implementation("androidx.room:room-runtime:2.4.3")
kapt("androidx.room:room-compiler:2.4.3")
@Entity

@Entity注解接受一个tableName参数,这个参数表示这个对象将会存储在哪张表中
Room规定每个被@Entity修饰的类都必须有一个主键@PrimaryKey

@PrimaryKey注解中autoGenerate参数表示主键是否可以通过数据库自行维护,一般是自增

@ColumnInfo注解是注解在成员变量上,表示这个成员变量会被存入哪一列,name参数表示列名,defaultValue表示默认值

@Ignore表示这个变量在存储数据库的时候会被忽略

@Embedded让当前字段也映射进表中,要求当前对象也需要用@Entity注解标记需要在注解上标记@SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED)否则编译会有报错

@SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED)表示该成员变量中的主键将会被忽略

/**
 * @PrimaryKey(autoGenerate = true)表示主键,其中参数autoGenerate表示主键可以由数据库自动生成
 * @ColumnInfo(name = "cacheId", defaultValue = "1")表示列的名字为cacheId, 默认值为1
 * @Ignore表示会忽略这个字段,不进行记录
 * @Embedded 让当前对象中的字段也映射进入表中,要求当前对象也需要用@Entity注解标记
 * @SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED)表示该对象中的主键将会失效
 */
@Entity(tableName = "room_test_table")
class RoomTestTable{
    @PrimaryKey(autoGenerate = true)
    var id : Long = 0
    @ColumnInfo(name = "cacheId", defaultValue = "1")
    var cache_id = 0
    @Ignore
    var bitmap: String = ""
    @SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED)
    @Embedded
    lateinit var user: User
    @ColumnInfo(name="test_list")
    lateinit var testList : MutableList<String>
}

@Entity(tableName = "user_table")
class User{
    @PrimaryKey(autoGenerate = false)
    lateinit var userName : String
    @ColumnInfo(name = "userage")
    var userAge : Int = 0
}
@DAO

@DAO注解需要标记在接口上,内部是实现数据库增删改查的功能
Room本身支持LiveData作为返回值

@Dao
interface TestDao {
    @Query("SELECT * FROM room_test_table")
    fun getAll() : List<RoomTestTable>

    @Query("SELECT * FROM room_test_table WHERE userName = :userName")
    fun getDataByName(userName : String) : RoomTestTable

    //可以通过LiveData 以观察者的形式获取数据库数据,可以避免不必要的npe,
    // 更重要的是他可以监听数据库的变化,一旦发生了insert update delete, room会自动读取表中最新的数据
    @Query("SELECT * FROM room_test_table")
    fun getLiveDataAll() : LiveData<List<RoomTestTable>>

    @Query("SELECT * FROM room_test_table WHERE userName = :userName")
    fun getLiveDataDataByName(userName : String) : LiveData<RoomTestTable>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertAll(vararg  roomTestTable: RoomTestTable)

    @Delete
    fun delete(roomTestTable: RoomTestTable)

    @Query("DELETE FROM room_test_table WHERE id = :id")
    fun delete(id : Long)
}
@Database @TypeConverters

@Database接口需要标记在抽象类上

@Database(entities = [RoomTestTable::class], version = 5, exportSchema = true, autoMigrations = [AutoMigration(from = 4, to = 5)])
//转换器,Room中不能被数据库存储的类型,可以通过转换器变成可以被存储的状态,并且在查询后自动转换类型
@TypeConverters(TestConverters::class)
abstract class TestDataBase : RoomDatabase() {
    abstract fun testDao() : TestDao
}
class TestConverters(){
    @TypeConverter
    fun listToString(list : MutableList<String>) : String{
        Log.d("TypeConverters", list.toString())
        return list.toString()
    }

    @TypeConverter
    fun stringToList(source: String) : MutableList<String>{
        val listStr = source.replace("[", "").replace("]", "")
        return listStr.trim().split(",").filter { it.isNotEmpty() }.toMutableList()
    }
}

@TypeConverters转换器,当Room中不能存放的对象在存放到表中会经过转换器转换。转化器的方法名不重要,重要的是入参和出参,在上面的Entity中testList是不能被数据库存储的,当存储到数据控中会经过转换器
fun listToString(list : MutableList<String>) : String
方法转换成String存入数据库。当查询出数据后会自动经过
fun stringToList(source: String) : MutableList<String>
方法转化成我们需要的类型。

注意在database抽象类上标记的为@TypeConverters 在转换器中标记的为@TypeConverter

数据库管理类与数据库升级

Room数据库可以记录每个版本的sql,并用于自动升级
在项目的gradle中加入如下代码

defaultConfig {
    applicationId "com.example.tdframe"
    //生成数据库SQL语句
    javaCompileOptions {
        annotationProcessorOptions {
            arguments += [
                    "room.schemaLocation":"$projectDir/schemas".toString(),
                    "room.incremental":"true",
                    "room.expandProjection":"true"]
        }
    }
}

之后每个版本的数据库都会生成相应的文件

数据库生成的文件记得保存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9g5gZJGq-1665969811492)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a2ea69f04c324b2399b8df8e7664ebf1~tplv-k3u1fbpfcp-watermark.image?)]

在@Database注解上开启exportSchema,和autoMigrations

AutoMigration注解接受两个参数,分别from和to从哪个数据库迁移数据到目标版本

@Database(entities = [RoomTestTable::class], version = 5, exportSchema = true, autoMigrations = [AutoMigration(from = 4, to = 5)])
//转换器,Room中不能被数据库存储的类型,可以通过转换器变成可以被存储的状态,并且在查询后自动转换类型
@TypeConverters(TestConverters::class)
abstract class TestDataBase : RoomDatabase() {
    abstract fun testDao() : TestDao
}
object DBManager {
    lateinit var  dataBase: TestDataBase
    fun init(context: Context) {
        //allowMainThreadQueries允许数据库在主线程上进行查询操作
        //
        dataBase = Room.databaseBuilder(context, TestDataBase::class.java, "TEST_DATA_BASE")
            .fallbackToDestructiveMigration()
                //允许数据库在主线程上进行查询操作
            //.allowMainThreadQueries()
                //指定数据库查询数据时候的线程池
            //.setQueryExecutor {  }
                //升级策略
            //.addMigrations()
            .build()
    }
}

之后修改@Entity修饰的类,数据库将会自动升级

@Entity(tableName = "room_test_table")
class RoomTestTable{
    @PrimaryKey(autoGenerate = true)
    var id : Long = 0
    @ColumnInfo(name = "cacheId", defaultValue = "1")
    var cache_id = 0
    @Ignore
    var bitmap: String = ""
    @SuppressWarnings(RoomWarnings.PRIMARY_KEY_FROM_EMBEDDED_IS_DROPPED)
    @Embedded
    lateinit var user: User
    @ColumnInfo(name="test_list")
    lateinit var testList : MutableList<String>
    //数据库升级后添加的列名
    @ColumnInfo(name = "add_column", defaultValue = "empty")
    lateinit var addColumn : String

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XuqxckBS-1665969811493)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/149096c5ab9b4814b32341e39cf27e2d~tplv-k3u1fbpfcp-watermark.image?)]

使用sqlite查看数据库

我们在查看数据的时候需要使用root后的手机或者使用AndroidStudio自带的虚拟机
虚拟机我们需要使用带GoogleAPIs的才能获取root权限

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w8xRC0fd-1665969811493)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/22afb33ebb824a719b47b04fdc1df8a3~tplv-k3u1fbpfcp-watermark.image?)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uA2qzWcA-1665969811494)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c189398ae67545ba83f115bd8f4e3059~tplv-k3u1fbpfcp-watermark.image?)]
下面是sqlite3的一些常用命令
.databases
列出附加到数据库的数据库和文件

.echo ON|OFF
打开/关闭 命令行回显

.exit
退出该命令行

.explain ?ON|OFF?
以合适的方式显示表头, 不带参数则为开启

.header ON;OFF
是否显示表头, 和 .explain 差别不是很大

.help
显示帮助信息

.import FILE TABLE
从文件中导入表

.indices ?TABLE?
显示索引

.load FILE ?ENTRY?
加载一个扩展库

.log FILE|off
是否记录日志,文件可以是标准输出/输入

.mode MODE ?TABLE?
设置输出模式, 模式可以是以下几种:
csv 以逗号分隔的值
column 表头左对齐(参见 .width)
html 显示 HTML 代码
insert SQL插入语句
line 一行一个值
list 值用 string 分隔
tabs 以 tab 分隔的值
tcl TCL 列表元素

.nullvalue STRING
以 STRING 代替 NULL 值的输出

.output FILENAME
输出到文件, 而不是显示在屏幕上

.output stdout
输出到屏幕上

.prompt MAIN CONTINUE
替换默认的命令提示信息, 默认就是 sqlite>

.quit
退出命令行

.read FILENAME
执行 FILENAME 中的 SQL

.restore ?DB? FILE
从文件中还原数据到表, 默认表为 main

.schema ?TABLE?
显示 CREATE 语句

.timeout MS
在 MS 时间内尝试打开被锁定的表

.vfsname ?AUX?
显示 VFS 栈信息

.width NUM1 NUM2 …
设置 column 模式中的列的宽度

.timer ON|OFF
显示CPU时间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值