简介
android架构组件中的数据持久化组件库,是在Sqlite上实现的一条ORM(对象关系映射,Object Relational Mapping)解决方案
相关概念
-
Database
使用@Database注解,要求继承RoomDatabase并且是抽象类,因为创建数据库比较消耗资源,所以一般都是使用单例模式
-
Entity
使用@Entity注解,每个Entity都对应这数据库中的一张表
-
DAO
使用@Dao注解,定义了访问表的接口,主要是在里面定义增删改查方法,并在方法上使用注解添加对应的SQL语句。一般情况下一个表对应一个Dao即可
简易的创建数据库
这里简易的创建一个数据库,步骤如下
先要在app的build.gradle中添加依赖
implementation "androidx.room:room-ktx:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
如果没有kapt,就在这个文件最上方添加(apt即表示注解处理器,kapt即kotlin annotation processing tool,因为用到了注解,所以需要这个)
apply plugin: 'kotlin-kapt'
1. 创建Entity
这里创建User类,并将表的名称重命名为users,设置主键自增
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) var id: Int,
var name: String
) {
constructor(name: String) : this(0, name)
}
当前,这里使用了数据列,使用普通类也是可以的
2. 创建DAO
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg user: User)
}
这里仅仅演示一下,插入的方法
3. 创建RoomDatabase的继承类
/**
* 如果Entity没有对应的表,将第一次获取RoomDatabase实例的时候创建表。
* 如果有Entity对应的表,就需要升级数据库版本号,并写对应的SQL语句
*/
@Database(
// 所有的Entity都需要在这里注册
entities = [User::class],
// 版本号,升级时需要加
version = 1
)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
// 使用伴生对象创建单例
companion object {
private var instance: AppDatabase? = null
fun getInstance(): AppDatabase = instance ?: synchronized(this) {
instance ?: buildDatabase()
}
}
}
private fun buildDatabase(): AppDatabase = Room.databaseBuilder(
MyApp.appInstance().applicationContext,
AppDatabase::
class.java,
"room_db"
)
.allowMainThreadQueries()//允许主线程访问,一般情况下是不允许的
.build()
如何调用UserDao里面的insert方法呢?
AppDatabase.getInstance().userDao().insert(User("张三"))
数据库在首次使用的时候就回去创建,然后根据Entity生成对应的表。
4. 初始化数据库填充表
有的时候,在创建数据库的时候需要填充一些数据进去,那么怎么做?
只需要在创建数据库的时候设置一个监听即可。
还是上面的数据库,我们需要在创建users表的时候添加四条数据进去,如下所示
private fun buildDatabase(): AppDatabase = Room.databaseBuilder(
MyApp.appInstance().applicationContext,
AppDatabase::
class.java,
"room_db"
)
.allowMainThreadQueries()//允许主线程访问,一般情况下是不允许的
.addCallback(callBack) // 设置监听
.build()
private val callBack = object : Callback() {
/**
* 首次创建数据库时候调用。
* 在所有表创建完成后调用
*/
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
val sql = "INSERT INTO \n" +
"USERS(name) \n" +
"VALUES \n" +
"(\"大牛\"),\n" +
"(\"二狗\"),\n" +
"(\"张三\"),\n" +
"(\"李四\");";
db.execSQL(sql)
}
/**
* 数据库被打开的时候调用
*/
override fun onOpen(db: SupportSQLiteDatabase) {
super.onOpen(db)
}
}
创建完成之后,先卸载之前的安装包,重新安装,然后拉出数据库查看,会发现users表已经创建,并且表中有四条数据
5. 升级数据库
有的时候,表改变了,就需要升级一下数据库。例如,我们在users表中添加列pwd,表示用户密码。
先在user类中添加变量pwd
@Entity(tableName = "users")
data class User(
@PrimaryKey(autoGenerate = true) var id: Int,
var name: String,
var pwd: String
) {
constructor(name: String) : this(0, name, "")
constructor(name: String, pwd: String) : this(0, name, pwd)
}
创建Migration的继承类
/**
* Migration中两个参数分别表示升级前和升级后的数据库版本
* migrate方法中写sql语句
*/
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE users ADD COLUMN pwd text NOT NULL DEFAULT \"\"")
}
}
然后在Room.databaseBuilder创建数据库的时候添加migration
private fun buildDatabase(): AppDatabase = Room.databaseBuilder(
MyApp.appInstance().applicationContext,
AppDatabase::
class.java,
"room_db"
)
.addMigrations(MIGRATION_1_2)
.build()
最后,在RoomDatabase的继承类中注解中更改version
@Database(
entities = [User::class],
version = 2
)