Android—Room 通用封装
2021-05-05 本文已影响0人
Kotyo
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>?
}
因为
Room
的Query
注解需要一个常量,这里就无法通过泛型去解决,所以就使用了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
从日志可以看出,这样封装是没什么问题的,好了,今天的内容到这就结束了。有什么问题,欢迎留言。