HarmonyOS 鸿蒙Next数据库Room

HarmonyOS 鸿蒙Next数据库Room

Room**

ORM(Object Relational Mapping):也叫对象关系映射。

我们使用的是面向对象的编程语言,则我们使用的数据库是关系型数据库,将面向对象的语言和面向关系的数据库之间建立一种映射关系就是ORM

Room由三部分组成:Entity,Dao,Database

Entity:定义封装实际数据的实体类,每个实体类在数据库中都有对应的表,并且表中的列根据实体类的字段自动生成 Dao:对数据库的各项操作进行封装 Database:定义数据库中的关键信息,包括数据库的版本号,包含的实体类,提供Dao层的访问实例

  1. 添加插件和依赖
plugins {
 ...
id("kotlin-kapt")
}
dependencies {
    implementation("androidx.room:room-runtime:2.1.0")
    kapt("androidx.room:room-compiler:2.1.0")
...
}
  1. 给每个实体类添加id字段,并且声明为实体类
@Entity //注解声明为实体类
data class User(val firstName:String,val lastName:String,val age:Int){
@PrimaryKey(autoGenerate=true) //添加id字段,@PrimaryKey声明为主键,并且设置为自动生成
var id:Long=0
}
  1. 创建UserDao接口,声明为Dao
@Dao
interface UserDao {
@Insert
fun insertUser(user: User):Long //添加数据并且返回主键id

@Update
fun updateUser(newUser: User)

@Delete
fun deleteUser(user: User)

//查找数据时或者以非实体类参数来进行增删改时,都必须要用@Query注解,可以动态检查SQL语法,如果有问题就会在编译时期报错
@Query("select * from User")
fun loadAllUsers():List<User>

@Query("delete from User where lastName=:lastName")
fun deleteUserByLastName(lastName:String):Int
    
@Query("delete from User") //删除表中所有数据
fun deleteAllUsers():Int //返回删除的行数
}
  1. 定义database:数据库的版本号,包含的实体类,提供Dao层的访问实例
[@Database](/user/Database)(version=1, entities = [User::class])
//必须继承自RoomDatabase,并且声明为抽象类
abstract class AppDatabase:RoomDatabase(){
    abstract fun userDao():UserDao //提供抽象方法获取Dao实例

    //用单例模式获取AppDatabase的实例
    companion object{
        private var instance:AppDatabase?=null
@Synchronized
fun getDatabase(context: Context):AppDatabase{
    instance?.let{
        return it //不为空直接返回
    }
  //如果为空则利用Room的databaseBuilder构建实例,第一个参数不能用context,否则容易内存泄漏,
  //第二个参数是AppDatabse的Class类型,第三个参数是数据库名
    return Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"app_database")
    .build().apply { instance=this }
}

    }
}

测试

val userDao=AppDatabase.getDatabase(this).userDao()
val user1=User("Tom","Brady",40)
val user2=User("Tom","Hanks",63)
binding.addDataBtn.setOnClickListener {
    thread{
        user1.id=userDao.insertUser(user1)
        user2.id=userDao.insertUser(user2)
    }
}
binding.updateDataBtn.setOnClickListener {
    thread{
        user1.age=42
        userDao.updateUser(user1)
    }
    binding.deleteDataBtn.setOnClickListener {
        thread{
            userDao.deleteUserByLastName("Hanks")
        }
    }
    binding.queryDataBtn.setOnClickListener {
        thread{
            for(user in userDao.loadAllUsers()){
                Log.d("MainActivity",user.toString())
            }
        }

由于数据库操作都是属于耗时操作,,Room中默认不允许在主线程中进行数据库操作,所以要开启子线程

但也可以在创建AppDatabase实例的时候就加入allowMainThreadQueries(),建议只在测试环境下使用

return Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"app_database")
.allowMainThreadQueries()
.build().apply { instance=this }

Room的数据库升级

新增表:

  1. 创建新的实体类
  2. 创建对应的Dao接口
  3. 修改AppDatabase
  4. 修改版本号,添加class文件
  5. 增加获得对应Dao的抽象方法
  6. 实现Migration的匿名类,在其中添加升级逻辑
[@Database](/user/Database)(version=2, entities = [User::class,Book::class]) //此处修改
abstract class AppDatabase: RoomDatabase(){
    abstract fun userDao():UserDao
    abstract fun bookDao():BookDao //此处修改



    companion object{
        ////此处修改
        val MIGRATION_1_2=object:Migration(1,2){
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("create table Book(id integer primary key autoincrement not null,name text not null,pages integer not null)") //注意建表语句要和实体类声明一致
                //这里Int对应Integer,String对应text
            }
        }
        private var instance:AppDatabase?=null
        @Synchronized
        fun getDatabase(context: Context):AppDatabase{
            instance?.let{
                return it
            }
            return Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"app_database").addMigrations(MIGRATION_1_2).build().apply { instance=this }
        }

    }
}

新增列:

  1. 增加实体类字段
  2. 修改AppDatabase @Database(version=3, entities = [User::class,Book::class]) //版本改为3 abstract class AppDatabase: RoomDatabase(){ abstract fun userDao():UserDao abstract fun bookDao():BookDao
companion object{
    val MIGRATION_2_3=object:Migration(2,3){
        override fun migrate(database: SupportSQLiteDatabase) {
            database.execSQL("alter table Book add column author text not null default 'unknown'") //default ‘unknown’表示默认为‘unknown’
        }
    }
    private var instance:AppDatabase?=null
    @Synchronized
    fun getDatabase(context: Context):AppDatabase{
        instance?.let{
            return it
        }
        return Room.databaseBuilder(context.applicationContext,AppDatabase::class.java,"app_database").addMigrations(MIGRATION_2_3).build().apply { instance=this }
    }

}

更多关于HarmonyOS 鸿蒙Next数据库Room的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

HarmonyOS的Room数据库是鸿蒙Next提供的持久化库,基于SQLite封装,支持Type-Safe API和编译时SQL校验。它包含三个核心组件:

  1. @Entity - 定义数据表结构
  2. @Dao - 提供增删改查接口
  3. @Database - 配置数据库实例

Room通过注解处理器在编译时生成实现类,支持Observable查询和协程/异步操作。使用时需在build.gradle中配置hvigor依赖:

"dependencies": {
    "room-runtime": "...",
    "room-compiler": "..."
}

更多关于HarmonyOS 鸿蒙Next数据库Room的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中使用Room数据库的配置和实现方式与Android基本一致。您提供的代码示例可以直接用于HarmonyOS应用开发,需要注意以下几点:

  1. 依赖配置方面,HarmonyOS Next使用自己的依赖管理方式,Room相关依赖需要替换为HarmonyOS提供的版本:
dependencies {
    implementation("ohos.room:room-runtime:1.0.0")
    annotationProcessor("ohos.room:room-compiler:1.0.0")
}
  1. 上下文获取方式不同,HarmonyOS中使用AbilityContext:
Room.databaseBuilder(context, AppDatabase::class.java, "app_database")
  1. 线程处理建议使用HarmonyOS的TaskDispatcher替代Thread:
GlobalTaskDispatcher.getDefaultTaskDispatcher().asyncDispatch {
    // 数据库操作
}
  1. 实体类定义和DAO接口的写法完全兼容,可以保持原样使用。

  2. 数据库升级迁移逻辑也保持一致,只需确保Migration中的SQL语句与实体类定义匹配。

HarmonyOS Next的Room实现保留了Android Room的核心功能,开发者可以平滑迁移现有代码。

回到顶部