Jetpak-Room数据库
作者:互联网
使用Room将数据保存到本地数据库
简介
Room持久库在SQLite之上提供了一个抽象层,以便在充分利用SQLite的强大功能的同时,能够流畅的访问数据库,具体来说,Room有以下优点:
- SQL查询的编译时验证
- 提供方便的注解,能最大减少重复和易错的样板代码
- 简化了数据库迁移路径
因此建议使用Room,而不是直接操作SQLite API。
设置
在 build.gradle
中,添加以下依赖:
//Kotlin annotation processing tool plugin
apply plugin: 'kotlin-kapt'
dependencies {
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
}
主要组件
Room包含了三个主要的组件:
- 数据库类
androidx.room.Database
: 此对象持有数据库,并为应用持久化数据的底层连接提供主要的入口。 - 数据实体
Entity
: 对应数据库表。 - 数据访问对象
DAO
: 一个接口或抽象类,提供数据库的CRUD
抽象操作方法,编译时Room会自动生成DAO
对应的实现实例。
androidx.room.Database
为app提供了关联数据库的DAO
实例。因此,app可以使用这些DAO
方法从数据库检索数据,以作为关联的数据实体对象的实例。此外,app还可以使用定义的数据实体对关联的表进行插入或更新单行或多行操作。下图展示了Room各组件间的关系:
示例
本部分展示了真实项目开发中的一个缩影。
项目中新建数据库相关的包
dao
:存放数据访问对象database
:存放数据库对象entity
: 存放数据表实体
数据实体类
以下代码通过注解@Entity
提供了一个数据实体LoginUser
,每个LoginUser
实例都代表tbl_login_user
表中的一行数据。
/**
* 登录用户
*/
@Entity(tableName = "tbl_login_user")
data class LoginUser(
@PrimaryKey
@ColumnInfo(name = "user_id")
val userId: String,
//登录名
@ColumnInfo(name = "login_name")
val loginName: String?,
//用于展示的名称
@ColumnInfo(name = "user_name")
val userName: String?,
//头像
@ColumnInfo(name = "avatar")
val avatar: String?,
//性别 0-男,1-女
@ColumnInfo(name = "gender")
val gender: Int?,
//加密后的密码
@ColumnInfo(name = "pwd_encrypt")
val pwdEncrypt: String?,
@ColumnInfo(name = "phone")
val phone: String?,
//第三方登录平台类型(目前未涉及)
@ColumnInfo(name = "third_type")
val thirdType: String?,
//第三方token登录(目前未涉及)
@ColumnInfo(name = "third_token")
val thirdToken: String?,
//token
@ColumnInfo(name = "token")
val token: String,
//刷新token
@ColumnInfo(name = "refresh_token")
val refreshToken: String?,
//是否记住密码:1-记住,0-不记住
@ColumnInfo(name = "remember_pwd")
val rememberPwd: Int,
//是否自动登录:1-自动登录,0-不自动登录
@ColumnInfo(name = "auto_login")
val autoLogin: Int,
//登录成功次数
@ColumnInfo(name = "login_count")
val loginCount: Int,
//账号是否启用:1-启用,0-不启用
@ColumnInfo(name = "enable")
val enable: Int,
//附加信息,扩展用
@ColumnInfo(name = "extra")
val extra: String?,
@ColumnInfo(name = "create_timestamp")
val createTimestamp: String,
@ColumnInfo(name = "update_timestamp")
val updateTimestamp: String,
@ColumnInfo(name = "create_time")
val createTime: String,
@ColumnInfo(name = "update_time")
val updateTime: String
)
DAO
以下代码通过@Dao
注解定义了一个LoginUserDao
接口(抽象类亦可),该接口为app提供了操作tbl_login_user
表的方法。
/**
* 提供登录用户表[LoginUser]相关的操作方法
*/
@Dao
interface LoginUserDao {
/**
* 插入或替换一条或多条记录
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrReplace(vararg loginUser: LoginUser)
/**
* 查询最近一条自动登录信息
*/
@Query("SELECT * FROM tbl_login_user WHERE auto_login == 1 ORDER BY update_timestamp DESC LIMIT 0,1")
fun queryLatestAutoLoginUser(): LoginUser
/**
* 删除旧数据,时间倒排1000条之前的数据
*/
@Query("DELETE FROM tbl_login_user WHERE user_id NOT IN (SELECT user_id FROM tbl_login_user ORDER BY update_timestamp DESC LIMIT 0,1000)")
fun deleteOldData()
}
Room数据库类
以下的代码通过注解@Database
定义了一个持有数据库的抽象类,此类提供了数据库的配置和app访问数据库的入口。定义此类必须满足以下条件:
- 必须带有注解
@Database
,注解中需要有entities
数组,数组中有数据表对应的数据实体。 - 必须继承自
RoomDatabase
,且为抽象类。 - 必须有定义无参的DAO抽象方法。
注意: 由于数据库实例的创建很耗资源,日常的单进程app场景中,应该尽可能的采用单例模式创建Room数据库实例。
/**
* app数据库
*/
@Database(version = 1, entities = [LoginUser::class])
abstract class AppDatabase : RoomDatabase() {
abstract fun loginUserDao(): LoginUserDao
companion object {
@Volatile
private var instance: AppDatabase? = null
/**
* 单例
*/
@Synchronized
fun getInstance(): AppDatabase {
if (instance == null) {
instance = Room.databaseBuilder(Utils.getApp(), AppDatabase::class.java, "app_data_db")
.fallbackToDestructiveMigration()//数据库版本发生变更策略:清除数据并重建数据表
.build()
}
return instance as AppDatabase
}
}
}
使用
通过AppDatabase
类中提供的抽象方法获取DAO
实例操作数据库:
val loginUserDao: LoginUserDao = AppDatabase.getInstance().loginUserDao()
val loginUser: LoginUser = loginUserDao.queryLatestAutoLoginUser()
标签:Room,val,数据库,String,Jetpak,ColumnInfo,name 来源: https://www.cnblogs.com/zhoux123/p/16094026.html