Android Jetpack系列03——Room框架使用

1、Room是什么?

答:Room是google官方出的一个关系型数据库框架。

2.Room相对于原生的SqliteHelper和现有的关系型数据库框架有什么优势和劣势?

答:官方给了3个优势:

  1. 相对于原生sqlitehelper,room可以在编译期检查sql语句的正确性,并且能检查sql语句中出现的表是否存在。这样可以避免一些sql语句错误出现在运行期。
  2. 相对于其他orm框架:更少的模板代码。
  3. 和Livedata框架能很好地结合。
  4. 相对于流行的第三方库,个人认为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?

答:

  1. 添加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框架。
Demo地址:https://github.com/dongzhixuanyuan/JetPackDemo

猜你喜欢

转载自blog.csdn.net/HelloMagina/article/details/84982846