Android—Room 通用封装

作者: Kotyo | 来源:发表于2021-05-05 15:03 被阅读0次

    Android-Room数据库(介绍)

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

    Android—Room自定义类型(TypeConverter)

    Android—Room 数据库迁移(Migration)

    前言

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

    封装

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

    abstract class BaseDao<T> {
        /**
         * 添加单个对象
         */
        @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<T>): List<Long>
    
        /**
         * 根据对象中的主键删除(主键是自动增长的,无需手动赋值)
         */
        @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<T>? {
            val query = SimpleSQLiteQuery(
                "select * from $tableName"
            )
            return doFindAll(query)
        }
    
        fun find(id: Long): T? {
            val query = SimpleSQLiteQuery(
                "select * from $tableName where id = ?", arrayOf<Any>(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<T>? {
            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<T>? {
            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<T>?
    
        @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<T>?
    
        @RawQuery
        protected abstract fun doQueryByOrder(query: SupportSQLiteQuery?): List<T>?
    }
    

    因为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<Person>() {
    
    }
    

    这里咱们只要去继承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<Person>?{
            return DBFactory.getInstance(mContext).getStudent().findAll()
        }
    
        fun doQueryByLimit():List<Person>?{
            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 通用封装

        本文链接:https://www.haomeiwen.com/subject/xfnkdltx.html