android 数据库简单理解使用

简介: android 数据库简单理解使用

Room 概述


Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。


Room 分析


Room 中注解和作用

  1. @Database:

@Database 注解的类必须是扩展 RoomDatabase 的抽象类;

包含具有 0 个参数且返回使用 @Dao 注释的类的抽象方法;

可以通过调用 Room.databaseBuilder() 或 Room.inMemoryDatabaseBuilder() 获取 Database 的实例;


  1. @Entity
    表示数据库中的表。


  1. @Dao

包含用于访问数据库的方法


inMemoryDatabaseBuilder 和 databaseBuilder


实际上两者注释中已经写得很不错了

inMemoryDatabaseBuilder 这种方式创建的数据库只能存在于内存中,一旦应用关闭数据就会被清空

我给你证明一下:

image.png

上面的gif做了这样一个事情

分别使用inMemoryDatabaseBuilder 和 databaseBuilder两种方式获取数据库db对象,然后分别在两个操作页面插入数据并查看数据插入成功与否

然后关闭应用再次打开,使用 databaseBuilder方式获取的数据库对象依然可以查询到数据,使用inMemoryDatabaseBuilder方式获取到的数据库对象不可以获取到数据,这证明了注释中说的是对的,也与我们前面说的结论呼应


Room 使用


简单使用

本例我们定义一个 Goods 的商品,商品包含自增 id 和商品名称, 然后实现对商品的增加、查询、删除等功能。主要展示商品增加和查询


  1. room 依赖
dependencies {
    def room_version = "2.3.0"
    implementation("androidx.room:room-runtime:$room_version")
    annotationProcessor "androidx.room:room-compiler:$room_version"
    // To use Kotlin annotation processing tool (kapt)
    kapt("androidx.room:room-compiler:$room_version")
    // To use Kotlin Symbolic Processing (KSP)
    ksp("androidx.room:room-compiler:$room_version")
    // optional - Kotlin Extensions and Coroutines support for Room
    implementation("androidx.room:room-ktx:$room_version")
    // optional - RxJava2 support for Room
    implementation "androidx.room:room-rxjava2:$room_version"
    // optional - RxJava3 support for Room
    implementation "androidx.room:room-rxjava3:$room_version"
    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "androidx.room:room-guava:$room_version"
    // optional - Test helpers
    testImplementation("androidx.room:room-testing:$room_version")
}
复制代码


  1. 定义 RoomDatabase 类
@Database(entities = arrayOf(Goods::class),version = 1)
abstract class GoodsDatabase: RoomDatabase() {
   abstract fun goodsDao():GoodsDao
}
复制代码


  1. 定义 Dao 类
@Dao
interface GoodsDao {
    @Query("SELECT * FROM goods")
    fun getAll(): List<Goods>
    @Query("SELECT * FROM goods WHERE id IN (:userIds)")
    fun loadAllByIds(userIds: IntArray): List<Goods>
    @Insert
    fun insertAll(vararg users: Goods)
    @Delete
    fun delete(user: Goods)
}
复制代码


  1. 定义 Goods 商品类
@Entity
data class Goods(
    @ColumnInfo(name = "goodsName") val name: String
) {
    @PrimaryKey(autoGenerate = true)
    var id: Long? =null
}
复制代码


因为商品的主键自动累加的,所有不应该在构造方法中传入,所以我们给他初始设置为 null,

注:必须设置为 null 才能实现自增,如果设置为具体值那么就无法自增了


  1. 插入数据
GlobalScope.launch {
               db.goodsDao().insertAll(Goods("阿娜卡列尼亚"))
           }
复制代码


  1. 获取数据并展示
GlobalScope.launch {
                val all = db.goodsDao().getAll()
                val sb = StringBuilder()
                for (good in all){
                    sb.append("商品id:${good.id}  商品名:${good.name} \n")
                }
                withContext(Dispatchers.Main){
                    tv_simpleuse.text=sb.toString()
                }
            }
复制代码


  1. 展示效果

image.png

关键知识点

Entity

  1. @Entity 中的字段如果我们不想生成数据库的一列,可以使用@Ignore 注解忽略
@Ignore val time:Long=0
复制代码
  1. 某个类继承了一个父类,让数据库不为父类字段生成列的方法
open class User {
        var picture: Bitmap? = null
    }
    @Entity(ignoredColumns = arrayOf("picture"))
    data class RemoteUser(
        @PrimaryKey val id: Int,
        val hasVpn: Boolean
    ) : User()
复制代码


本例中 RemoteUser 继承了 User,User 中有一个 picture 字段,我们不想数据库的表生成一个 picture 列,所以在 RemoteUser 的 Entity 注解中添加 ignoredColumns 忽略。

  1. 如何为实体类中的索引添加顺序

定义实体类的时候注解中加入如下代码:

@Entity(indices = arrayOf(Index(value = ["last_name", "address"])))
复制代码


Dao (插入查询操作,部分是抄的官网)

如何设置在主线程可以调用数据库查询

构建 db 对象的时候调用 allowMainThreadQueries 方法

虽说可以设置,但是建议你 100%不要考虑这么做

val db =
            Room.databaseBuilder(applicationContext, GoodsDatabase::class.java, "goods")
                .allowMainThreadQueries()
                .build()
复制代码


插入方法

插入数据的方法可以有一个或多个参数,如果是一个参数可以返回主键,如果是多个参数会返回主键的数组

@Insert(onConflict = OnConflictStrategy.REPLACE)
        fun insertUsers(vararg users: User)
复制代码


更新数据
@Dao
    interface MyDao {
        @Update
        fun updateUsers(vararg users: User)
    }
复制代码


删除数据
@Dao
    interface MyDao {
        @Delete
        fun deleteUsers(vararg users: User)
    }
复制代码


查询
简单查询
@Dao
    interface MyDao {
        @Query("SELECT * FROM user")
        fun loadAllUsers(): Array<User>
    }
复制代码


带查询条件的查询
@Dao
    interface MyDao {
        @Query("SELECT * FROM user WHERE age > :minAge")
        fun loadAllUsersOlderThan(minAge: Int): Array<User>
    }
复制代码


:minAge 绑定参数与 minAge 方法参数进行匹配

返回列表子集

下面代码查询结果会自动赋值到 NameTuple 中

@Dao
    interface MyDao {
        @Query("SELECT first_name, last_name FROM user")
        fun loadFullName(): List<NameTuple>
    }
复制代码

大多数情况下,您只需获取实体的几个字段。例如,您的界面可能仅显示用户的名字和姓氏,而不是用户的每一条详细信息。


查询数量不定的参数

部分查询可能要求您传入数量不定的参数,参数的确切数量要到运行时才知道。例如,您可能希望从部分区域中检索所有用户的相关信息。Room 知道参数何时表示集合,并根据提供的参数数量在运行时自动将其展开。

@Dao
    interface MyDao {
        @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
        fun loadUsersFromRegions(regions: List<String>): List<NameTuple>
    }
复制代码


使用 suspend 修饰 dao 中的方法

使用 suspend 修饰方法,通过协程使这些方法变为异步,避免我们在主线程中进行操作

@Update
        suspend fun updateUsers(vararg users: User)
复制代码
使用 Livedata 观察数据库操作


@Dao
    interface MyDao {
        @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
        fun loadUsersFromRegionsSync(regions: List<String>): LiveData<List<User>>
    }
复制代码


定义对象之间的关系

暂时先不深入这里,回头单开文章讲:

官网参考:

developer.android.google.cn/training/da…


预填数据库

从 assets 目录预装

如需从位于应用 assets/ 目录中的任意位置的预封装数据库文件预填充 Room 数据库,请先从 RoomDatabase.Builder 对象调用 createFromAsset() 方法,然后再调用 build()

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromAsset("database/myapp.db")
        .build()
复制代码


从文件预装

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
        .createFromFile(File("mypath"))
        .build()
复制代码


数据库迁移

Room 持久性库支持通过 Migration 类进行增量迁移以满足此需求。每个 Migration 子类通过替换 Migration.migrate() 方法定义 startVersion 和 endVersion 之间的迁移路径。当应用更新需要升级数据库版本时,Room 会从一个或多个 Migration 子类运行 migrate() 方法,以在运行时将数据库迁移到最新版本:

val MIGRATION_1_2 = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, `name` TEXT, " +
                "PRIMARY KEY(`id`))")
    }
}
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE Book ADD COLUMN pub_year INTEGER")
    }
}
Room.databaseBuilder(applicationContext, MyDb::class.java, "database-name")
        .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build()



相关文章
|
7月前
|
网络协议 关系型数据库 MySQL
如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】
如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】
|
7月前
|
存储 数据库连接 数据库
Android数据存储:解释SQLite数据库在Android中的使用。
Android数据存储:解释SQLite数据库在Android中的使用。
86 0
|
6月前
|
数据库 Android开发 数据安全/隐私保护
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
244 2
|
6月前
|
SQL 存储 数据库
48. 【Android教程】数据库:SQLite 的使用
48. 【Android教程】数据库:SQLite 的使用
84 1
|
6月前
|
存储 缓存 数据库
Android之SQLite数据库使用详解
Android之SQLite数据库使用详解
|
6月前
|
存储 数据库 Android开发
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
在 Android Studio 中结合使用 SQLite 数据库实现简单的注册和登录功能
185 0
|
7月前
|
数据库 Android开发
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
Android数据库框架-GreenDao入门,2024年最新flutter 页面跳转动画
|
7月前
|
存储 SQL 数据库
【Android 从入门到出门】第六章:使用Room数据库并测试
【Android 从入门到出门】第六章:使用Room数据库并测试
107 4
|
7月前
|
网络协议 关系型数据库 MySQL
安卓手机termux上安装MariaDB数据库并实现公网环境下的远程连接
安卓手机termux上安装MariaDB数据库并实现公网环境下的远程连接
238 0
|
7月前
|
数据库 Android开发 数据库管理
【Android】使用android studio查看内置数据库信息
【Android】使用android studio查看内置数据库信息
580 0