一分耕耘、一分收获,为了使用时忘记,或无处查询,本文记录的是Room的一些使用方法,并持续更新
Room持久性库在SQLite的基础上提供了一个抽象层
1.1 创建Entity(实体类),并指定数据库表
@Entity注解是标识实体类,并通过tableName指定该实体类指向的表名,@PrimaryKey注解标识主键
@Entity Represents a table within the database. Room creates a table for each class that has @Entity annotation, the fields in the class correspond to columns in the table. Therefore, the entity classes tend to be small model classes that don't contain any logic
创建步骤:
- 创建实体类
- 通过Entity注解标识实体类,通过tableName指定表名
//例1 创建表
@Entity(tableName = "user_table")
class User{
@PrimaryKey(autoGenerate = true)
var id: Int = 0
var firstName: String? = null
var lastName: String? = null
var age: Int = 0
}
//例2 创建表
@Entity(
tableName = "table_pic",
indices = [Index(
value = ["imageId"],
unique = true
)]
)
class PicEntity : Pic() {
}
1.2 创建Dao接口或抽象类,注解定义数据的增删改查方法
@Dao DAOs are reponsible for defining the methods that access the database. This is the place where we write our queries
创建步骤:
- 创建Dao接口或者抽象
- 在接口或者抽象类中定义方法,通过注解定义数据的增删改查方法,如下所示
//例1 接口
@Dao
interface UserDao {
@Query("SELECT * FROM user_table ORDER BY id ASC")
fun readAllData(): LiveData<List<User>>
}
//例2 抽象类
@Dao
abstract class FestivalDao : DaoProxy() {
}
1.3 创建数据库Database,继承RoomDatabase
@Database Contains the database holder and serves as the main access point for the underlying connection to your app's data
创建步骤:
- 创建抽象类Database继承RoomDatabase
- 定义抽象方法返回Dao实例
- 通过@Database注解标识数据库,通过entities指定有哪些实体类即对应哪些表,version指定版本号
@Database(entities = [User::class], version = 1, exportSchema = false)
abstract class UserDatabase: RoomDatabase() {
abstract fun userDao(): UserDao
private class DatabaseCallback : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
PictorialLog.i(TAG, "onCreate")
super.onCreate(db)
}
override fun onOpen(db: SupportSQLiteDatabase) {
PictorialLog.i(TAG, "onOpen")
super.onOpen(db)
}
override fun onDestructiveMigration(db: SupportSQLiteDatabase) {
PictorialLog.w(TAG, "onDestructiveMigration")
}
}
companion object {
private const val TAG = "UserDatabase"
@JvmStatic
val instance: UserDatabase by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
val context = BaseApplication.getInstance()
createDB(context)
}
private fun createDB(appContext: Context): UserDatabase {
val migrations = mutableListOf(
object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
}
}
)//迁移后需要修改DATABSASE_VERSION
val database = Room.databaseBuilder(appContext, UserDatabase::class.java,"user_database")
.fallbackToDestructiveMigration()//如果数据库版本升级(查不到对应的migration),则丢弃原数据,适用于room初始版本
.allowMainThreadQueries()
.addCallback(DatabaseCallback())
.addMigrations(*migrations.toTypedArray())
.build()
return database
}
}
}
1.4 增加字段
在class User 中增加字段,如增加city
@Entity(tableName = "user_table")
class User{
@PrimaryKey(autoGenerate = true)
var id: Int = 0
var firstName: String? = null
var lastName: String? = null
var age: Int = 0
var city: String? = null
}
同时记得更新对应的equals、hashCode、update方法
1.5 更改索引约束条件
@Entity(tableName = "user_table", indices = [Index(
value = [firstName, lastName],
unique = true
)])
class User{
@PrimaryKey(autoGenerate = true)
var id: Int = 0
var firstName: String? = null
var lastName: String? = null
var age: Int = 0
var city: String? = null
}
数据库升级更新索引
database.execSQL("DROP INDEX IF EXISTS `index_user_table_firstName`")
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_user_table_firstName_lastName` ON `user_table` (`firstName`,`lastName`)")
2 数据库升级
2.1 修改版本号
2.2 增加Migration
val migrations = mutableListOf(
object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE user_table ADD COLUMN school DEFAULT NULL")
}
}
)//迁移后需要修改DATABSASE_VERSION
3 遇到的问题
3.1 更新数据不生效
// 判断数据库中是否已经存在相同日期的数据
val existingEntity = getEntityByDate(entity.date)
if (existingEntity != null) {
// 如果存在,则更新该数据
updateEntity(entity)
} else {
// 如果不存在,则插入一条新数据
insertEntity(entity)
}
执行上述代码更新数据不生效,原因为entity的id与existingEntity的id不一致,导致更新失败,修复后的代码为:
// 判断数据库中是否已经存在相同日期的数据
val existingEntity = getEntityByDate(entity.date)
if (existingEntity != null) {
// 如果存在,则将entity的信息赋给existingEntity,然后进行更新
existingEntity.count = entity.count
updateEntity(existingEntity)
} else {
// 如果不存在,则插入一条新数据
insertEntity(entity)
}