HarmonyOS 5 实战教程:基于 RdbStore 的数据库 CRUD 完整指南
前言
大家好,我是若城!👋 欢迎来到 HarmonyOS 5 开发实战系列。
在移动应用开发中,数据持久化是不可或缺的核心功能。无论是用户信息存储、应用配置管理,还是业务数据缓存,都需要可靠的数据库支持。本文将通过一个完整的"言记"应用中的"树洞"模块,深入讲解如何在 HarmonyOS 5 中使用 RdbStore 实现高效的数据库 CRUD 操作。
你将学到:
-
RdbStore 的核心概念和优势
-
数据模型的设计与实现
-
完整的 CRUD 操作封装
-
实际项目中的最佳实践
RdbStore 简介
什么是 RdbStore?
RdbStore 是字节跳动为鸿蒙生态开发的高性能数据库组件,专门为 HarmonyOS 应用提供强大的数据持久化能力。
核心特性
开发效率
-
基于 DTO 对象的操作方式,告别复杂的 SQL 语句
-
自动化数据库创建和版本升级管理
-
智能的查询结果反序列化
性能优化
-
内置查询优化器和索引管理
-
支持批量操作,提升数据处理效率
-
完善的连接池管理
稳定可靠
-
完备的单元测试覆盖
-
全链路日志记录和性能监控
-
异常处理和数据恢复机制
资源链接
项目演示
本文以"言记"应用中的"树洞"模块为例,展示 RdbStore 的完整使用流程。应用包含三个核心界面:
-
数据展示界面 - 显示所有树洞记录
-
内容编辑界面 - 创建和编辑树洞内容
-
数据管理界面 - 查询和删除操作

项目演示图
环境准备
项目目录结构
合理的项目结构是开发效率的基础,推荐按功能模块组织代码:

项目目录结构
src/main/ets/
├── common/api/ # API 接口层
├── model/ # 数据模型
├── pages/ # 页面组件
├── types/ # 类型定义
└── utils/ # 工具类
安装依赖
在 DevEco Studio 中执行以下命令安装 RdbStore:
ohpm install rdbstore

安装插件
数据模型设计
业务数据接口定义
首先定义业务层面的数据结构,这有助于保持代码的清晰性和可维护性:
// src/main/ets/types/types.ets
export interface TreeHoleData {
id: number, // 唯一标识符
title: string, // 树洞主题
content: string, // 树洞内容
moods: string, // 心情标签(逗号分隔)
createTime: string, // 创建时间
isAnonymous: boolean // 是否匿名发布
}
代码解析:
-
TreeHoleData接口定义了业务层的数据结构 -
每个字段都有明确的业务含义和数据类型
-
这个接口将作为前端组件和数据库实体之间的桥梁
数据库实体模型
基于业务接口,创建对应的数据库实体模型:
// src/main/ets/model/TBTreeHole.ets
import { Columns, ColumnType, Entity } from "rdbstore"
/**
* 树洞数据库实体模型
* 使用 @Entity 装饰器标记为数据库表
*/
@Entity({
tableName: 'tree_hole' // 指定数据库表名
})
export class TreeHoleEntity {
// 数据库主键,自增长
@Columns({
name: 'uid', // 数据库列名
type: ColumnType.INTEGER, // 数据类型:整型
autoincrement: true, // 自动递增
isPrimaryKey: true // 设为主键
})
uid: number | undefined = undefined
// 业务ID字段
@Columns({ name: 'id', type: ColumnType.INTEGER })
id: number = 0
// 树洞标题
@Columns({ name: 'title', type: ColumnType.TEXT })
title: string = ''
// 树洞内容
@Columns({ name: 'content', type: ColumnType.TEXT })
content: string = ''
// 心情标签(存储为逗号分隔的字符串)
@Columns({ name: 'moods', type: ColumnType.TEXT })
moods: string = ''
// 创建时间(存储为字符串格式)
@Columns({ name: 'createTime', type: ColumnType.TEXT })
createTime: string = ''
// 匿名状态(布尔值存储为 BLOB 类型)
@Columns({ name: 'isAnonymous', type: ColumnType.BLOB })
isAnonymous: boolean = false
}
代码解析:
-
@Entity 装饰器:将类标记为数据库实体,
tableName指定对应的数据库表名 -
@Columns 装饰器:定义数据库列的属性
-
name:数据库中的列名 -
type:数据类型,必须指定 -
isPrimaryKey:是否为主键 -
autoincrement:是否自动递增(仅适用于整型主键)
-
-
字段设计考虑:
-
uid:数据库主键,自增长,确保唯一性 -
id:业务层面的ID,便于业务逻辑处理 -
其他字段对应业务需求,类型选择合理
-
数据类型说明
RdbStore 支持四种基本数据类型,选择合适的类型对性能和存储效率至关重要:
/**
* RdbStore 支持的数据库列类型
* 选择合适的类型对性能和存储效率至关重要
*/
export enum ColumnType {
/**
* 文本类型 - 存储字符串数据
* 适用场景:标题、内容、时间字符串等
*/
TEXT = 'TEXT',
/**
* 整型 - 存储整数数据
* 数值范围:±2,147,483,647
* 适用场景:ID、计数器、状态码等
*/
INTEGER = 'INTEGER',
/**
* 浮点型 - 存储小数数据
* 适用场景:价格、评分、坐标等
*/
REAL = 'REAL',
/**
* 二进制对象 - 存储二进制数据
* 适用场景:布尔值、图片、文件等
*/
BLOB = 'BLOB'
}
类型选择建议:
-
TEXT:字符串数据,如标题、内容
-
INTEGER:整数数据,如ID、数量
-
REAL:浮点数据,如价格、评分
-
BLOB:二进制数据,如布尔值、文件
列属性配置
@Columns 装饰器支持丰富的配置选项,满足各种业务需求:
/**
* 数据库列配置接口
* 提供了丰富的约束和转换选项
*/
export interface ColumnInfo {
/**
* 数据库列名
* 不指定时使用属性名
*/
name?: string
/**
* 列数据类型(必填)
* 决定了数据在数据库中的存储格式
*/
type: ColumnType
/**
* 主键约束
* 确保数据唯一性,一个表只能有一个主键
*/
isPrimaryKey?: boolean
/**
* 自增约束
* 仅适用于整型主键,自动生成唯一值
*/
autoincrement?: boolean
/**
* 唯一性约束
* 确保列值在表中唯一,插入时会进行校验
*/
unique?: boolean
/**
* 非空约束
* 确保列值不能为空
*/
notNull?: boolean
/**
* 类型转换器
* 用于业务类型与数据库类型之间的转换
* 例如:Date 对象 ↔ 时间戳字符串
*/
convertor?: ClassConstructor<PropertyConverter<Object, Object>>
}
配置选项说明:
-
约束配置:主键、唯一性、非空等约束确保数据完整性
-
自动化功能:自增主键减少手动ID管理的复杂性
-
类型转换:支持复杂对象与数据库类型的自动转换
工具类封装
数据库相关功能封装
// src/main/ets/utils/dbHelper.ets
import { EventParamsBaseType, IEventSender, ILog, Rdb, RdbDao, RdbDatabase } from "rdbstore";
import { relationalStore } from "@kit.ArkData";
import { hilog } from "@kit.PerformanceAnalysisKit";
import { TreeHoleEntity } from "../model/TBTreeHole";
// 日志级别枚举定义
enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3
}
class DBLog implements ILog {
private static domain: number = 0x0000;
private static isLogEnabled: boolean = true; // 总开关
private static logLevel: LogLevel = LogLevel.DEBUG; // 默认级别
// 日志级别枚举
static setLogLevel(level: LogLevel): void {
DBLog.logLevel = level;
}
// 全局开关控制
static enableLog(): void {
DBLog.isLogEnabled = true;
}
static disableLog(): void {
DBLog.isLogEnabled = false;
}
d(tag: string, message: string): void {
if (!DBLog.isLogEnabled || DBLog.logLevel > LogLevel.DEBUG) {
return;
}
hilog.debug(DBLog.domain, tag, '%{public}s', message);
}
i(tag: string, message: string): void {
if (!DBLog.isLogEnabled || DBLog.logLevel > LogLevel.INFO) {
return;
}
hilog.info(DBLog.domain, tag, '%{public}s', message);
}
w(tag: string, message: string): void {
if (!DBLog.isLogEnabled || DBLog.logLevel > LogLevel.WARN) {
return;
}
hilog.warn(DBLog.domain, tag, '%{public}s', message);
}
e(tag: string, message: string): void {
if (!DBLog.isLogEnabled || DBLog.logLevel > LogLevel.ERROR) {
return;
}
hilog.error(DBLog.domain, tag, '%{public}s', message);
}
}
class DBEventSender implements IEventSender{
send(key: string, params: Record<string, EventParamsBaseType>): void {
console.log(key)
}
}
export default class DbHelper {
static readonly DB_VERSION: number = 6
static readonly DB_NAME: string = "treeHole.db"
private static INSTANCE: DbHelper;
private context?: Context;
private db?: RdbDatabase;
// 私有化构造函数
private constructor() {
}
// 单例获取方法
static getInstance(): DbHelper {
if (!DbHelper.INSTANCE) {
DbHelper.INSTANCE = new DbHelper();
}
return DbHelper.INSTANCE;
}
async init(context: Context) {
DBLog.enableLog();
DBLog.setLogLevel(LogLevel.DEBUG);
this.db = Rdb.databaseBuilder(context, {
version: DbHelper.DB_VERSION,
dbName: DbHelper.DB_NAME,
entities: [TreeHoleEntity],
migrations: [],
encrypt: false,
securityLevel: relationalStore.SecurityLevel.S1,
autoMigrate: true
})
.setLogger(new DBLog())
.setEvent(new DBEventSender())
.build()
await this.initDb()
}
getDb(): RdbDatabase {
if (!this.db) {
throw new Error('db not initialized');
}
return this.db;
}
initDb() {
this.db?.initTask
}
async getTBTreeHoleDAO(): Promise<RdbDao<TreeHoleEntity>> {
if (!this.db) {
throw new Error('db not initialized');
}
return await this.db.getDao(TreeHoleEntity)
}
}
代码解析:
-
初始化数据库
-
获取数据库帮助类单例实例
API 接口设计
数据访问层是连接业务逻辑和数据存储的桥梁,良好的API设计能大大提升开发效率:
// src/main/ets/common/api/treeHoleApi.ets
import { TreeHoleEntity } from "../../model/TBTreeHole"
import DbHelper from "../../utils/dbHelper"
/**
* 树洞数据访问接口
* 封装所有与树洞相关的数据库操作
*
* 设计原则:
* - 单一职责:只处理树洞相关的数据操作
* - 统一接口:提供一致的异步操作接口
* - 错误处理:统一的异常处理机制
*/
export default class DBTreeHoleApi {
/**
* 创建新的树洞记录
*
* @param entity 树洞实体对象
* @returns 影响的行数,>0 表示成功
*
* 使用示例:
* const result = await DBTreeHoleApi.insertCard(newTreeHole);
* if (result > 0) console.log('创建成功');
*/
static async insertCard(entity: TreeHoleEntity): Promise<number> {
// 获取数据访问对象(DAO)
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
// 执行插入操作,返回影响行数
return await dao.insert(entity)
}
/**
* 批量创建树洞记录
* 适用于数据导入、批量操作等场景
*
* @param entries 树洞实体数组
* @returns 影响的行数
*
* 性能优势:
* - 减少数据库连接次数
* - 事务性操作,要么全部成功要么全部失败
*/
static async batchInsertCard(entries: Array<TreeHoleEntity>): Promise<number> {
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
return await dao.batchInsert(entries)
}
/**
* 删除指定的树洞记录
*
* @param entity 要删除的树洞实体(需要包含主键信息)
* @returns 影响的行数,>0 表示删除成功
*
* 注意事项:
* - 删除操作不可逆,建议在UI层添加确认提示
* - 可以考虑软删除(标记删除状态)而非物理删除
*/
static async deleteCard(entity: TreeHoleEntity): Promise<number> {
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
return await dao.delete(entity)
}
/**
* 查询所有树洞记录
*
* @returns 树洞实体数组,可能为空数组
*
* 查询逻辑:
* - 使用谓词构建器构建查询条件
* - 不添加 where 条件表示查询全部
* - 结果按创建时间倒序排列(最新的在前)
*/
static async queryAllCard(): Promise<TreeHoleEntity[] | undefined> {
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
// 构建查询:无条件查询所有记录
const entities = await dao.predicatesBuilder().build().run()
return entities
}
/**
* 根据ID查询特定树洞记录
*
* @param id 树洞的唯一标识符(uid字段)
* @returns 匹配的树洞实体数组
*
* 查询逻辑:
* - 获取 uid 属性的谓词对象
* - 使用 equalTo 方法构建等值查询条件
* - 返回数组格式(虽然ID唯一,但保持接口一致性)
*/
static async queryItemCard(id: number): Promise<TreeHoleEntity[] | undefined> {
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
// 获取 uid 字段的属性对象
const uIdProp = dao.getProperty('uid')
// 构建查询条件:uid = id
const entities = await dao.predicatesBuilder()
.where(uIdProp.equalTo(id))
.build()
.run()
return entities
}
/**
* 更新树洞记录
*
* @param entity 包含更新数据的树洞实体(必须包含主键)
* @returns 影响的行数,>0 表示更新成功
*
* 更新策略:
* - 根据主键(uid)定位记录
* - 更新所有非主键字段
* - 保持数据完整性和一致性
*/
static async updateCard(entity: TreeHoleEntity): Promise<number> {
const dao = await DbHelper.getInstance().getTBTreeHoleDAO()
return await dao.update(entity)
}
}
API设计亮点:
-
静态方法:无需实例化,直接调用,简化使用
-
统一返回:增删改操作返回影响行数,查询操作返回实体数组
-
异步操作:所有方法都是异步的,避免阻塞UI线程
应用初始化
依赖导入
在应用入口文件中导入必要的依赖:
// src/main/ets/entryability/EntryAbility.ets
// HarmonyOS 核心能力包
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
// 应用工具类
import PreferencesUtils from '../utils/PreferencesUtils';
import DbHelper from '../utils/dbHelper';
import { CustomStyle } from "../types/types"
导入说明:
-
系统能力包:HarmonyOS 提供的核心功能模块
-
工具类:应用自定义的工具和辅助类
-
类型定义:TypeScript 类型定义,提供类型安全
生命周期初始化
在应用的关键生命周期中初始化存储组件:
// 在 onWindowStageCreate 生命周期中初始化存储组件
onWindowStageCreate(windowStage: window.WindowStage): void {
// 初始化首选项存储
PreferencesUtils.createPreferences(this.context);
// 初始化数据库
// 获取数据库帮助类单例实例
DbHelper.getInstance();
// 使用应用上下文初始化数据库连接
DbHelper.getInstance().init(this.context);
// 其他窗口初始化逻辑...
}
初始化流程解析:
-
首选项初始化:创建首选项存储实例,用于轻量级配置存储
-
数据库初始化:
-
获取数据库帮助类的单例实例
-
使用应用上下文初始化数据库连接
-
自动创建表结构和处理版本升级
-
-
时机选择:在
onWindowStageCreate中初始化确保:-
应用上下文已经准备就绪
-
在UI创建之前完成数据层初始化
-
避免后续操作中的初始化延迟
-
CRUD 操作实战
完成基础配置后,我们来实现完整的数据库 CRUD 操作。以下代码展示了在实际业务场景中如何使用 RdbStore 进行数据操作。
Create - 数据创建
依赖导入
// src/main/ets/pages/CreateTreeHolePage.ets
// 数据访问接口
import DBTreeHoleApi from "../common/api/treeHoleApi"
// 数据模型
import { TreeHoleEntity } from "../model/TBTreeHole"
// UI交互组件
import { promptAction } from '@kit.ArkUI'
// 路由导航
import router from '@ohos.router'
核心创建逻辑
以下是完整的数据创建和更新逻辑,支持新建和编辑两种模式:
/**
* 提交树洞数据的核心方法
* 支持新建和编辑两种模式,统一处理业务逻辑
*/
async submitTreeHole() {
console.log('=== 开始提交树洞数据 ===')
console.log('当前内容:', this.content)
console.log('当前标题:', this.title)
console.log('是否编辑模式:', this.isEditMode)
// 数据验证:标题和内容不能都为空
if (this.content.trim().length === 0 && this.title.trim().length === 0) {
console.log('提交失败:标题和内容不能都为空')
promptAction.showToast({
message: '请输入标题或内容',
duration: 2000
})
return
}
console.log('开始提交树洞数据...')
this.isSubmitting = true; // 设置提交状态,防止重复提交
try {
if (this.isEditMode && this.editingTreeHole) {
// 编辑模式:更新现有树洞
await this.updateExistingTreeHole()
} else {
// 创建模式:插入新树洞
await this.createNewTreeHole()
}
} catch (error) {
console.error('提交树洞数据时发生错误:', JSON.stringify(error))
promptAction.showToast({
message: '操作失败,请重试',
duration: 2000
})
} finally {
this.isSubmitting = false // 重置提交状态
}
}
/**
* 更新现有树洞记录
* 保持原有的创建时间和ID,只更新可编辑字段
*/
private async updateExistingTreeHole() {
console.log('执行更新操作...')
// 更新树洞数据
this.editingTreeHole.title = this.title
this.editingTreeHole.content = this.content
this.editingTreeHole.moods = this.selectedMoods.join(',')
this.editingTreeHole.isAnonymous = this.isAnonymous
console.log('准备更新的数据:', JSON.stringify({
id: this.editingTreeHole.id,
title: this.editingTreeHole.title,
content: this.editingTreeHole.content,
moods: this.editingTreeHole.moods,
createTime: this.editingTreeHole.createTime,
isAnonymous: this.editingTreeHole.isAnonymous
}))
// 调用数据库更新操作
const updateResult = await DBTreeHoleApi.updateCard(this.editingTreeHole)
console.log('数据库更新结果:', updateResult)
if (updateResult > 0) {
console.log('树洞数据更新成功,更新行数:', updateResult)
promptAction.showToast({
message: '树洞更新成功',
duration: 2000
})
router.back() // 返回上一页
} else {
promptAction.showToast({
message: '树洞更新失败',
duration: 2000
})
console.error('数据库更新失败,返回值:', updateResult)
}
}
/**
* 创建新的树洞记录
* 生成新的ID和时间戳,插入完整的数据记录
*/
private async createNewTreeHole() {
console.log('执行创建操作...')
// 生成业务数据
const uniqueId = this.generateUniqueId(); // 生成唯一业务ID
const currentTime = this.getCurrentDateTime(); // 获取当前时间
console.log('生成的唯一ID:', uniqueId)
console.log('当前时间:', currentTime)
console.log('选中的心情标签:', this.selectedMoods)
// 构建新的树洞实体
const newTreeHole = new TreeHoleEntity();
newTreeHole.id = uniqueId; // 业务ID
newTreeHole.title = this.title; // 标题
newTreeHole.content = this.content; // 内容
newTreeHole.moods = this.selectedMoods.join(','); // 心情标签(逗号分隔)
newTreeHole.createTime = currentTime; // 创建时间
newTreeHole.isAnonymous = this.isAnonymous; // 匿名状态
console.log('准备插入的数据:', JSON.stringify({
id: newTreeHole.id,
title: newTreeHole.title,
content: newTreeHole.content,
moods: newTreeHole.moods,
createTime: newTreeHole.createTime,
isAnonymous: newTreeHole.isAnonymous
}))
// 调用数据库插入操作
const insertResult = await DBTreeHoleApi.insertCard(newTreeHole)
console.log('数据库插入结果:', insertResult)
if (insertResult > 0) {
console.log('树洞数据插入成功,插入行数:', insertResult)
promptAction.showToast({
message: '树洞发布成功',
duration: 2000
})
router.back() // 返回上一页
} else {
promptAction.showToast({
message: '树洞发布失败',
duration: 2000
})
console.error('数据库插入失败,返回值:', insertResult)
}
}
代码解析:
-
数据验证:在提交前验证必填字段,提升用户体验
-
状态管理:使用
isSubmitting防止重复提交 -
模式区分:根据
isEditMode区分新建和编辑操作 -
错误处理:完善的异常捕获和用户提示
-
日志记录:详细的操作日志,便于调试和问题定位
Read - 数据读取
依赖导入
// src/main/ets/pages/TreeHoleListPage.ets
// 数据访问接口
import DBTreeHoleApi from "../common/api/treeHoleApi"
// 数据模型
import { TreeHoleEntity } from "../model/TBTreeHole"
// UI交互组件
import { promptAction } from '@kit.ArkUI'
数据查询实现
实现完整的数据查询和状态管理逻辑:
/**
* 页面状态定义
*/
@State treeHoles: TreeHoleEntity[] = [] // 树洞数据列表
@State showDialog: boolean = false // 对话框显示状态
@State isLoading: boolean = false // 加载状态
@State isEmpty: boolean = false // 空数据状态
/**
* 页面显示时的生命周期回调
* 每次页面显示时都会重新加载数据,确保数据最新
*/
onPageShow() {
console.log('页面显示,开始加载树洞数据')
this.loadMyTreeHoles()
}
/**
* 切换对话框显示状态
*/
handleShow = () => {
this.showDialog = !this.showDialog
}
/**
* 加载树洞数据的核心方法
* 从数据库查询所有树洞记录并更新UI状态
*/
async loadMyTreeHoles() {
console.log('开始加载树洞数据...')
this.isLoading = true // 显示加载状态
try {
// 调用API查询所有树洞数据
const allTreeHoles = await DBTreeHoleApi.queryAllCard()
if (allTreeHoles && allTreeHoles.length > 0) {
console.log('查询到的树洞数量:', allTreeHoles.length)
// 数据处理:按创建时间倒序排列(最新的在前)
this.treeHoles = allTreeHoles.sort((a, b) => {
return new Date(b.createTime).getTime() - new Date(a.createTime).getTime()
})
this.isEmpty = false
console.log('树洞数据加载成功')
} else {
// 无数据情况
this.treeHoles = []
this.isEmpty = true
console.log('暂无树洞数据')
}
} catch (error) {
console.error('加载树洞数据失败:', error)
promptAction.showToast({
message: '数据加载失败,请重试',
duration: 2000
})
this.treeHoles = []
this.isEmpty = true
} finally {
this.isLoading = false // 隐藏加载状态
}
}
/**
* 刷新数据
* 提供下拉刷新功能
*/
async refreshData() {
console.log('用户触发数据刷新')
await this.loadMyTreeHoles()
promptAction.showToast({
message: '刷新完成',
duration: 1000
})
}
代码解析:
-
状态管理:使用多个状态变量管理不同的UI状态
-
生命周期:在
onPageShow中加载数据,确保数据实时性 -
数据排序:按创建时间倒序显示,提升用户体验
-
空状态处理:区分加载中、空数据、错误等不同状态
-
用户反馈:提供加载提示和操作结果反馈
Delete - 数据删除
实现安全的数据删除操作,包含确认机制和状态同步:
/**
* 删除树洞记录
* 包含确认提示和状态同步机制
*
* @param item 要删除的树洞实体
*/
async deleteTreeHole(item: TreeHoleEntity) {
console.log('准备删除树洞:', item.id, item.title)
try {
// 显示确认对话框(可选,根据UI设计决定)
// const confirmed = await this.showConfirmDialog('确定要删除这条树洞吗?')
// if (!confirmed) return
// 调用删除API
const deleteResult = await DBTreeHoleApi.deleteCard(item)
if (deleteResult > 0) {
console.log('数据库删除成功,影响行数:', deleteResult)
// 从本地列表中移除(优化用户体验,避免重新查询)
this.treeHoles = this.treeHoles.filter(treeHole => treeHole.id !== item.id)
// 更新空状态
this.isEmpty = this.treeHoles.length === 0
promptAction.showToast({
message: '删除成功',
duration: 2000
})
console.log('树洞删除成功:', item.id)
} else {
console.error('数据库删除失败,返回值:', deleteResult)
promptAction.showToast({
message: '删除失败,请重试',
duration: 2000
})
}
} catch (error) {
console.error('删除树洞时发生错误:', error)
promptAction.showToast({
message: '删除失败,请重试',
duration: 2000
})
}
}
/**
* 批量删除树洞(扩展功能)
* 适用于管理界面的批量操作
*
* @param items 要删除的树洞实体数组
*/
async batchDeleteTreeHoles(items: TreeHoleEntity[]) {
console.log('准备批量删除树洞,数量:', items.length)
if (items.length === 0) {
promptAction.showToast({
message: '请选择要删除的项目',
duration: 2000
})
return
}
try {
let successCount = 0
let failCount = 0
// 逐个删除(也可以考虑实现批量删除API)
for (const item of items) {
try {
const result = await DBTreeHoleApi.deleteCard(item)
if (result > 0) {
successCount++
} else {
failCount++
}
} catch (error) {
console.error('删除单个项目失败:', item.id, error)
failCount++
}
}
// 刷新数据列表
await this.loadMyTreeHoles()
// 显示操作结果
if (failCount === 0) {
promptAction.showToast({
message: `成功删除 ${successCount} 条记录`,
duration: 2000
})
} else {
promptAction.showToast({
message: `删除完成:成功 ${successCount} 条,失败 ${failCount} 条`,
duration: 3000
})
}
console.log('批量删除完成,成功:', successCount, '失败:', failCount)
} catch (error) {
console.error('批量删除过程中发生错误:', error)
promptAction.showToast({
message: '批量删除失败',
duration: 2000
})
}
}
代码解析:
-
安全删除:可以添加确认对话框,防止误删
-
状态同步:删除成功后立即更新本地状态,提升响应速度
-
错误处理:完善的异常处理和用户提示
-
批量操作:提供批量删除功能,适用于管理场景
-
用户反馈:详细的操作结果提示
结语
RdbStore 为 HarmonyOS 5 应用开发提供了强大而易用的数据持久化解决方案。通过合理的架构设计和最佳实践,我们可以构建出高性能、可维护的数据层。 希望本文能够帮助你快速掌握 RdbStore 的使用方法,在实际项目中发挥其强大的能力。如果你有任何问题或建议,欢迎在评论区交流讨论!
更多推荐


所有评论(0)