引言

本文章旨在记录学习Android JetPack库下的Room数据库的使用,不作过于深入原理的讲解,如有问题和建议请留言讨论。

1、Room 库概念及架构示意图

概念

Google的介绍:   处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的使用场景是缓存相关的数据,这样一来,当设备无法访问网络时,用户仍然可以在离线状态下浏览该内容,   Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库   Room 库具有一下优势:

针对 SQL 查询的编译时验证可最大限度减少重复和容易出错的样板代码的方便注解简化了数据库迁移路径

架构示意图

主要组件

Room 包含三个主要组件

数据库类(Room Database),用于保存数据库并作为应用持久性数据底层连接的主要访问点数据实体(Entities),用于表示应用的数据库中的表数据访问对象 (Data Access Objects【Dao】),提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法

2、使用(Kotlin版【带注释】)

效果图展示

Android Room数据库操作

附上代码库地址:https://github.com/zqf-dev/ZRoomCode

依赖项添加

在build.gradle(Project)文件下添加版本

ext {

roomVersion = '2.4.2'

}

在build.gradle(app)文件下添加

plugins {

id 'com.android.application'

id 'kotlin-android'

// 添加kapt注解处理器

id 'kotlin-kapt'

}

android {

//排除原子函数模块并防止出现警告

packagingOptions {

exclude 'META-INF/atomicfu.kotlin_module'

}

kotlinOptions {

jvmTarget = "1.8"

}

}

dependencies{

//ktx

implementation 'androidx.core:core-ktx:1.7.0'

// room

implementation "androidx.room:room-ktx:$rootProject.roomVersion"

kapt "androidx.room:room-compiler:$rootProject.roomVersion"

// 展示数据 adapter

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.7'

}

实体类(Entities)创建

数据库(Database)创建

*注:exportSchema:是否允许数据库架构将导出到给定的文件夹中【 默认true 】

/**

* Author: zqf

* Date: 2022/05/11

* 数据库创建

* entities: 实体类

* version: 数据库初始版本号

* exportSchema: 是否允许数据库架构将导出到给定的文件夹中【 默认true 】

*

*/

@Database(entities = [User::class], version = 1, exportSchema = false)

abstract class ZRoomDB : RoomDatabase() {

//创建userDao

abstract fun userDao(): UserDao

}

数据访问对象 (DAO)创建

/**

* Author: zqf

* Date: 2022/05/11

* 数据访问对象

*/

@Dao

interface UserDao {

// 查询

@Query("SELECT * FROM loginUser")

fun queryAllUser(): MutableList

//根据姓名参数查询

@Query("SELECT * FROM loginUser WHERE name = :name")

fun queryFindUser(name: String): User?

// 添加单条数据

@Insert

fun addUser(vararg user: User)

// 添加批量数据

@Insert(onConflict = OnConflictStrategy.REPLACE)

fun addBatchUser(list: MutableList)

// 更新某一个数据

@Update

fun updateUser(vararg user: User)

//更新所有数据

@Query("UPDATE loginUser set age='50'")

fun updateAll()

//删除某一个数据

@Delete

fun deleteSingle(vararg user: User)

//删除表里所有数据

@Query("DELETE FROM loginUser")

fun deleteAllUser()

}

数据管理类封装

/**

* Author: zqf

* Date: 2022/05/11

* 数据库管理工具

*/

object DbManager {

//数据库名

private const val dbName: String = "zroom"

//懒加载创建数据库

val db: ZRoomDB by lazy {

Room.databaseBuilder(

App.app.applicationContext, ZRoomDB::class.java, dbName

).allowMainThreadQueries()//允许在主线程操作

.addCallback(DbCreateCallBack)//增加回调监听

.addMigrations()//增加数据库迁移

.build()

}

private object DbCreateCallBack : RoomDatabase.Callback() {

//第一次创建数据库时调用

override fun onCreate(db: SupportSQLiteDatabase) {

super.onCreate(db)

Log.e("TAG", "first onCreate db version: " + db.version)

}

}

}

使用方法

class MainActivity : AppCompatActivity() {

private val TagL = MainActivity::class.java.simpleName

private lateinit var queryBtn: Button

private lateinit var insertBtn: Button

private lateinit var updateBtn: Button

private lateinit var deleteBtn: Button

private lateinit var resultRecycle: RecyclerView

private var list = mutableListOf()

var userDao: UserDao = DbManager.db.userDao()

private val userAdapter by lazy {

UserAdapter(R.layout.user_item_layout)

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

findVbId()

}

private fun findVbId() {

queryBtn = findViewById(R.id.query)

insertBtn = findViewById(R.id.insert)

updateBtn = findViewById(R.id.update)

deleteBtn = findViewById(R.id.delete)

resultRecycle = findViewById(R.id.result_recycle)

resultRecycle.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)

resultRecycle.adapter = userAdapter

userAdapter.addChildClickViewIds(R.id.item_delete, R.id.item_modify)

queryBtn.setOnClickListener { query() }

insertBtn.setOnClickListener { insertSingle() }

deleteBtn.setOnClickListener { delete() }

updateBtn.setOnClickListener { update() }

userAdapter.setOnItemChildClickListener { _, view, position ->

when (view.id) {

R.id.item_delete -> singleDel(list[position])

R.id.item_modify -> singleModify(list[position])

}

}

insertAll()

}

/**

* 查询

*/

private fun query() {

list = userDao.queryAllUser()

Log.e(TagL, list.toString())

userAdapter.setList(list)

}

/**

* 默认插入批量数据

*/

private fun insertAll() {

runBlocking {

if (userDao.queryAllUser().size == 0) {

val mutableList: MutableList = mutableListOf()

for (a in 1..3) {

val user = User("张三$a", 20 + a, "贵阳市观山湖区$a", "")

mutableList.add(user)

}

userDao.addBatchUser(mutableList)

ToastUtil.show("批量新增数据成功")

}

query()

}

}

/**

* 插入单条数据

*/

private fun insertSingle() {

val age = Random.nextInt(20, 40)

val user = User("小二", age, "贵阳市观山湖区", "")

userDao.addUser(user)

ToastUtil.show("新增一条数据成功")

query()

}

/**

* 删除表里的所有数据

*/

private fun delete() {

userDao.deleteAllUser()

ToastUtil.show("删除所有数据成功")

query()

}

/**

* 更新所有数据

*/

private fun update() {

userDao.updateAll()

ToastUtil.show("更新表里所有年龄数据成功")

query()

}

/**

* 删除loginUser表里的指定删除某一个

*/

private fun singleDel(singleUser: User) {

userDao.deleteSingle(singleUser)

ToastUtil.show("删除单条数据成功")

query()

}

/**

* 修改数据表里某一个对象的字段值

*/

private fun singleModify(user: User) {

user.aliasName = "修改的" + user.aliasName

user.age = 100

user.ads = "修改的地址白云区"

userDao.updateUser(user)

ToastUtil.show("更新单条数据成功")

list.clear()

query()

}

}

数据库升级

Room 同时支持自动和手动方式进行增量迁移*注:Room 在 2.4.0-alpha01 及更高版本中支持自动迁移。如果您的应用使用的是较低版本的 Room,则必须手动定义迁移。

1、手动迁移

在实体类User里新增 字段gender

/**

* Author: zqf

* Date: 2022/05/11

* 数据实体

* TODO

* 1、@Entity:Room实体类注解 ---> 默认情况下,Room 将【类名称】用作数据库【表名称】

* 注:如果您希望【数据库表】具有不同的名称,请设置 @Entity 注解的 tableName 属性

* 2、PrimaryKey: 主键( autoGenerate = true 主键自增 ),作用:唯一标识相应数据库表中的每一行

* 3、@ColumnInfo:数据库表字段---> 默认情况下,使用【字段名称】作为数据库中的【列名称】

* 注:如果您希望【数据表里的列】具有不同的名称,请将 @ColumnInfo 注解添加到该字段并设置 name 属性

* 4、Ignore: 默认情况下,Room 会为实体中定义的每个字段创建一个列。 如果您不想保留该字段,则可以使用 @Ignore 为字段添加注解

*/

@Entity(tableName = "loginUser")

data class User(

@PrimaryKey(autoGenerate = true)

var id: Int = 0,

@ColumnInfo(name = "name")

var aliasName: String = "",

var age: Int = 0,

var ads: String = "",

@Ignore

var avatar: String = "",

//数据库升级时测试的 新增字段

var gender: Int = 0

) {

constructor(aliasName: String, age: Int, ads: String, avatar: String) : this() {

this.aliasName = aliasName

this.age = age

this.ads = ads

this.avatar = avatar

}

}

1)创建 Migration 类,版本从v1—>v2,添加了‘gender’字段 默认值为12)SQL语句:   2.1)数据库表里增加字段    ALTER TABLE loginUser ADD gender INTEGER Default 1 not null   2.2)数据库新增表    CREATE TABLE Car (id INTEGER, name TEXT, PRIMARY KEY(id))

/**

* 数据库升级

*/

private object ZMigration : Migration(1, 2) {

override fun migrate(database: SupportSQLiteDatabase) {

Log.e(TagL, "执行数据库升级: ")

//loginUser表中增加字段gender

database.execSQL("ALTER TABLE loginUser ADD gender INTEGER Default 1 not null")

//新建汽车数据表

//database.exceSQL("CREATE TABLE Car (id INTEGER, name TEXT, PRIMARY KEY(id))")

}

}

//懒加载创建数据库

//懒加载创建数据库

val db: ZRoomDB by lazy {

Room.databaseBuilder(

App.app.applicationContext, ZRoomDB::class.java, dbName

).allowMainThreadQueries()//允许在主线程操作

.addCallback(DbCreateCallBack)//增加回调监听

.addMigrations(ZMigration)//增加数据库迁移

.build()

}

修改Database version版本为 2,依次调整

@Database(entities = [User::class], version = 2, exportSchema = false)

abstract class ZRoomDB : RoomDatabase() {

//创建userDao

abstract fun userDao(): UserDao

}

执行结果:

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: