1、Room是什么?
答:Room是google官方出的一个关系型数据库框架。
2.Room相对于原生的SqliteHelper和现有的关系型数据库框架有什么优势和劣势?
答:官方给了3个优势:
- 相对于原生sqlitehelper,room可以在编译期检查sql语句的正确性,并且能检查sql语句中出现的表是否存在。这样可以避免一些sql语句错误出现在运行期。
- 相对于其他orm框架:更少的模板代码。
- 和Livedata框架能很好地结合。
- 相对于流行的第三方库,个人认为room的优点是接口调用非常集中,所有的访问数据库的方法,都需要的interface Dao中定义,这样的话后续在维护跟数据库相关代码时,会发现入口非常集中。不像Greendao那种,调用时根据需求去组装sql操作,room是如果你需要做什么操作,就需要先在dao类中进行定义。
劣势:
room只支持一对一的关系,不支持一对多或者多对一.
@Entity()
data class Person(@PrimaryKey var name: String, var pets:List<Pet>)
@Entity
data class Pet(@PrimaryKey var size:Int)
上述代码是无法通过编译的,因为person中只包含了多个pet.那如果要表达这种关系,可以反过来思考,一个person可以含有多个pet,但是一个pet只属于一个person,就可以改成下面这个样子。
@Entity()
data class Person(@PrimaryKey var name: String, var pets:List<Pet>)
@Entity(foreignKeys = arrayOf(ForeignKey(entity = Person::class, parentColumns = arrayOf("name"), childColumns = arrayOf("ownerId"))))
data class Pet(@PrimaryKey var size:Int,var ownerId:String)
3、怎么使用Room?
答:
- 添加gradle依赖 android.arch.persistence.room:runtime:1.0.0
添加注解处理依赖:
kapt android.arch.persistence.room:compiler:1.0.0
2.定义表结构:
@Entity(tableName = "student",indices =[Index(value = ["address"],unique = false)] )
data class Student(
@PrimaryKey
@SerializedName("name")
val name: String,
@SerializedName("number")
@ColumnInfo(name="number_column")
val number: Int,
@SerializedName("address")
val address: String
)
@Entity:表示该类将被映射为一张room数据库的表;
@PrimaryKey:主键
@SerializeName 该字段被序列化时的key 字段名
@ColumnInfo:该字段在数据库中的列名
3、创建数据库。
@Database(entities = arrayOf(Student::class),version = 1,exportSchema = false)
abstract class StudentDb : RoomDatabase() {
companion object {
fun create(context: Context, useInmemory: Boolean = false): StudentDb {
val databaseBuilder = if (useInmemory) {
Room.inMemoryDatabaseBuilder(context, StudentDb::class.java)
} else {
Room.databaseBuilder(context,StudentDb::class.java,"student.db")
}
return databaseBuilder.fallbackToDestructiveMigration()
.allowMainThreadQueries().build()
}
}
abstract fun getStudentDao():StudentQueryDao
}
4、定义数据库操作接口。
@Dao
interface StudentQueryDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(students: List<Student>): Unit
@Query("SELECT * FROM student WHERE name LIKE :queryName ORDER BY number_column ASC")
fun queryByName(queryName: String): DataSource.Factory<Int, Student>
@Update(onConflict = OnConflictStrategy.REPLACE)
fun updateStudentByName(student: Student)
}
Room的数据库接口比较有意思,可以使用@Insert @Query @Update 的注解。
5、创建数据库并访问接口。
var db = StudentDb.create(context.applicationContext, false)
fun queryStudent(name:String,size:Int,boundaryCallback: PagedList.BoundaryCallback<Student>?):LiveData<PagedList<Student>>{
val results = db.getStudentDao().queryByName(name)
return LivePagedListBuilder<Int, Student>(results, 10)
.setBoundaryCallback(boundaryCallback).build()
}
fun addStudents(students:List<Student>){
db.getStudentDao().insert(students)
}
fun updateStudent(student: Student) {
db.getStudentDao().updateStudentByName(student)
}
6、数据库迁移和更新,room支持也非常完善,并且简单。
在构建Room.databaseBuilder().addMigrations(new Migration()),就可以添加更新和迁移操作了。
总结下来:Room数据库使用非常简单,调理很清晰。如果项目需要新增数据库时,可以考虑用Room框架。