Android—Room 通用封装

Android-Room数据库(介绍)

Android-Room数据库-多表查询(Relationships)

Android—Room自定义类型(TypeConverter)

Android—Room 数据库迁移(Migration)

前言

平常咱们使用数据库的时候,基本操作都差不太多,,但如果操作不同的数据时,就需要写较多的重复的代码,仅仅是因为操作的类对象变化了。下面咱们就通过泛型去封装一层BaseDao,减少后期的模板代码。Room的普通用法请看上面的链接。

封装

当您看完了上面的基本用法后,我相信下面的代码对于您来说也没什么难度了。

abstract class BaseDao {
    /**
     * 添加单个对象
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(obj: T): Long

    /**
     * 添加数组对象数据
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(vararg objs: T): LongArray?

    /**
     * 添加对象集合
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    abstract fun insert(personList: List): List

    /**
     * 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
     */
    @Delete
    abstract fun delete(obj: T)

    /**
     * 根据对象中的主键更新(主键是自动增长的,无需手动赋值)
     */
    @Update
    abstract fun update(vararg obj: T): Int

    fun deleteAll(): Int {
        val query = SimpleSQLiteQuery(
            "delete from $tableName"
        )
        return doDeleteAll(query)
    }

    fun findAll(): List? {
        val query = SimpleSQLiteQuery(
            "select * from $tableName"
        )
        return doFindAll(query)
    }

    fun find(id: Long): T? {
        val query = SimpleSQLiteQuery(
            "select * from $tableName where id = ?", arrayOf(id)
        )
        return doFind(query)
    }

    /**
     * [params] 列名
     * [value] 列的值
     */
    fun deleteByParams(params: String, value: String): Int {
        val query = SimpleSQLiteQuery("delete from $tableName where $params='${value}'")
        Log.d("ez", "deleteByParams: ${"delete from $tableName where $params='${value}'"}")
        return doDeleteByParams(query)
    }

    /**
     * 分页查询,支持传入多个字段,但必须要按照顺序传入
     * key = value,key = value 的形式,一一对应(可以使用 stringbuilder 去构造一下,这里就不演示了)
     */
    fun doQueryByLimit(vararg string: String, limit: Int = 10, offset: Int = 0): List? {
        val query =
            SimpleSQLiteQuery("SELECT * FROM $tableName WHERE ${string[0]} = '${string[1]}' limit $limit offset $offset")
        return doQueryByLimit(query)
    }

    /**
     * 降序分页查询
     */
    fun doQueryByOrder(vararg string: String, limit: Int = 10, offset: Int = 10): List? {
        val query =
            SimpleSQLiteQuery("SELECT * FROM $tableName ORDER BY ${string[0]} desc limit '${limit}' offset '${offset}'")
        return doQueryByLimit(query)
    }

      /**
      * 获取表名
       */
    val tableName: String
        get() {
            val clazz = (javaClass.superclass.genericSuperclass as ParameterizedType)
                .actualTypeArguments[0] as Class<*>
            val tableName = clazz.simpleName
            Log.d("ez", "getTableName: -->$tableName")
            return tableName
        }

    @RawQuery
    protected abstract fun doFindAll(query: SupportSQLiteQuery?): List?

    @RawQuery
    protected abstract fun doFind(query: SupportSQLiteQuery?): T

    @RawQuery
    protected abstract fun doDeleteAll(query: SupportSQLiteQuery?): Int

    @RawQuery
    protected abstract fun doDeleteByParams(query: SupportSQLiteQuery?): Int

    @RawQuery
    protected abstract fun doQueryByLimit(query: SupportSQLiteQuery?): List?

    @RawQuery
    protected abstract fun doQueryByOrder(query: SupportSQLiteQuery?): List?
}

因为RoomQuery注解需要一个常量,这里就无法通过泛型去解决,所以就使用了SupportSQLiteQuery类和@RawQuery注解,这样咱们就可以通过sql语句来封装一些通用的操作,就解决了Query注解无法直接使用泛型的问题,详细用法请看上面的方法。

使用

@Entity
class Person {
    @PrimaryKey(autoGenerate = true)
    var id: Long?
    var bh: String 
    var name: String? = null
    var loginName: String? = null
    var feature: ByteArray? = null
    var isPolice: Boolean = false

    constructor(
        id: Long? = null,
        name: String?,
        feature: ByteArray? = null,
        bh: String,
        loginName: String? = null,
        isPolice: Boolean = false
    ) {
        this.id = id
        this.name = name
        this.feature = feature
        this.bh = bh
        this.loginName = loginName
        this.isPolice = isPolice
    }

    override fun toString(): String {
        return "Person(id=$id, bh=$bh, name=$name,loginName=$loginName, isPolice=$isPolice)"
    }
}
@Dao
abstract class StudentDao : BaseDao() {

}

这里咱们只要去继承BaseDao然后传入需要操作的对象类型即可,通用的操作已封装在上层,无需再重复写了

构建 RoomDatabase

@Database(entities = [Person::class],version = 1,exportSchema = false)
abstract class DBFactory :RoomDatabase(){

    abstract fun getStudent():StudentDao

    companion object{
        private const val DB_NAME = "DBFactory.db"
        @Volatile
        private var dbFactory:DBFactory?=null

        @Synchronized
        fun getInstance(context: Context):DBFactory{
            if (dbFactory == null) {
                dbFactory = create(context)
            }
            return dbFactory!!
        }

        fun create(context: Context):DBFactory{
            return Room.databaseBuilder(context,DBFactory::class.java, DB_NAME).build()
        }

    }
}

构建 DBManager

class DBManager(context:Context) {

    private var mContext: Context = context

    companion object{
        @Volatile
        private var instance:DBManager?=null
        @Synchronized
        fun getInstance(context: Context):DBManager{
            if(instance == null){
                instance = DBManager(context)
            }
            return instance!!
        }
    }

    fun insertPerson(name: String?, feature: ByteArray?=null,bh:String?,loginName:String?, isPolice:Boolean?):Long {
        val person = Person(name = name,feature = feature,bh = bh!!,loginName = loginName,isPolice = isPolice!!)
        return DBFactory.getInstance(mContext).getStudent().insert(person)
    }

    fun deleteByParams(params:String,value:String):Int{
        return DBFactory.getInstance(mContext).getStudent().deleteByParams(params,value)
    }

    fun countPerson():Int?{
        return DBFactory.getInstance(mContext).getStudent().findAll()?.size
    }

    fun findAll():List?{
        return DBFactory.getInstance(mContext).getStudent().findAll()
    }

    fun doQueryByLimit():List?{
        return DBFactory.getInstance(mContext).getStudent().doQueryByLimit("name","aa")
    }
}

使用方法

            getInstance(applicationContext).insertPerson("aa", null, "aa11", "aa11", false)
            getInstance(applicationContext).insertPerson("bb", null, "bb11", "bb11", false)
            getInstance(applicationContext).insertPerson("cc", null, "cc11", "cc11", false)
            getInstance(applicationContext).insertPerson("dd", null, "dd11", "dd11", false)
            getInstance(applicationContext).insertPerson("ee", null, "ee11", "ee11", false)
            getInstance(applicationContext).insertPerson("ff", null, "ff11", "ff11", false)
            getInstance(applicationContext).insertPerson("gg", null, "gg11", "gg11", false)
            getInstance(applicationContext).insertPerson("hh", null, "hh11", "hh11", false)
            getInstance(applicationContext).insertPerson("ii", null, "ii11", "ii11", false)
            getInstance(applicationContext).insertPerson("jj", null, "jj11", "jj11", false)
            getInstance(applicationContext).insertPerson("kk", null, "kk11", "kk11", false)
            getInstance(applicationContext).insertPerson("ll", null, "ll11", "ll11", false)
            getInstance(applicationContext).insertPerson("mm", null, "mm11", "mm11", false)
            getInstance(applicationContext).insertPerson("nn", null, "nn11", "nn11", false)

查询

 val findAll = getInstance(applicationContext).findAll()
   if (findAll != null) {
        for (i in findAll) {
          Log.d(TAG, "obj-->${i}")
      }
  }
查询.png

从日志可以看出,这样封装是没什么问题的,好了,今天的内容到这就结束了。有什么问题,欢迎留言。

你可能感兴趣的:(Android—Room 通用封装)