📝 文章概述

数据持久化是任何应用的核心功能之一。HarmonyOS提供的RelationalStore是一个功能强大的关系型数据库系统,基于SQLite实现。本文将通过日记应用的实际案例,深入讲解RelationalStore的使用方法、最佳实践和性能优化技巧。

🎯 为什么选择RelationalStore?

技术优势

mindmap
  root((RelationalStore))
    功能特性
      SQL支持
      事务管理
      索引优化
      数据加密
    性能优势
      高效查询
      批量操作
      内存优化
      异步API
    易用性
      简洁API
      Promise支持
      类型安全
      错误处理
    安全性
      数据隔离
      权限控制
      安全等级
      数据备份

与其他方案对比

特性 RelationalStore Preferences 文件存储
数据结构 关系型表格 键值对 自定义
查询能力 ⭐⭐⭐⭐⭐ SQL ⭐⭐ Key查询 ⭐ 文件遍历
性能 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
数据量 大量数据 少量配置 任意
事务支持
适用场景 复杂数据、查询需求 简单配置 文件、媒体

🚀 快速开始

第一步:数据库配置与初始化

import { relationalStore } from '@kit.ArkData'

// 数据库管理类
export class Rdb {
  rdbStore: relationalStore.RdbStore | null = null
  private sqlCreateTable: string = ''
  
  // 🔥 数据库配置
  private STORE_CONFIG: relationalStore.StoreConfig = {
    name: 'diary.db',         // 数据库文件名
    securityLevel: 1,         // 安全等级:1=最高
    encrypt: false,           // 是否加密
    customDir: ''             // 自定义目录(可选)
  }
  
  constructor(sqlCreateTable: string) {
    this.sqlCreateTable = sqlCreateTable
  }
  
  // 🔥 获取或创建数据库实例
  async getRdbStore() {
    // 如果已存在,直接返回
    if (this.rdbStore != null) {
      return this.rdbStore.executeSql(this.sqlCreateTable);
    }
    
    try {
      // 获取应用上下文
      const context = getContext();
      
      // 创建或打开数据库
      this.rdbStore = await relationalStore.getRdbStore(
        context, 
        this.STORE_CONFIG
      );
      
      console.info('✅ 数据库创建/打开成功');
      
      // 创建表
      await this.rdbStore.executeSql(this.sqlCreateTable);
      console.info('✅ 数据表创建成功');
      
    } catch (error) {
      console.error('❌ 数据库初始化失败:', error);
      throw error;
    }
  }
  
  // 🔥 关闭数据库
  async closeStore() {
    if (this.rdbStore) {
      await this.rdbStore.close();
      this.rdbStore = null;
      console.info('✅ 数据库已关闭');
    }
  }
  
  // 🔥 删除数据库
  async deleteStore() {
    const context = getContext();
    await relationalStore.deleteRdbStore(context, this.STORE_CONFIG.name);
    this.rdbStore = null;
    console.info('✅ 数据库已删除');
  }
}

第二步:定义数据模型

// 日记数据模型
export class DiaryRecord {
  id?: number
  title: string
  content: string
  time: string
  
  constructor(title: string, content: string, time: string) {
    this.title = title
    this.content = content
    this.time = time
  }
}

// 日记记录集合类
export class DiaryRecordSet {
  private records: DiaryRecord[] = []
  
  // 添加记录
  addRecord(record: DiaryRecord) {
    this.records.push(record)
  }
  
  // 转换为数组
  convertToArray(): DiaryRecord[] {
    return this.records
  }
  
  // 获取数量
  get length(): number {
    return this.records.length
  }
}

第三步:创建数据表

// SQL建表语句
const SQL_CREATE_TABLE = `
  CREATE TABLE IF NOT EXISTS diary (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT NOT NULL,
    time TEXT NOT NULL
  )
`;

// 创建索引(优化查询性能)
const SQL_CREATE_INDEX = `
  CREATE INDEX IF NOT EXISTS idx_time ON diary(time DESC)
`;

// 初始化数据库
const rdb = new Rdb(SQL_CREATE_TABLE);
await rdb.getRdbStore();

// 创建索引
if (rdb.rdbStore) {
  await rdb.rdbStore.executeSql(SQL_CREATE_INDEX);
  console.info('✅ 索引创建成功');
}

💡 CRUD操作实战

1. 插入数据(Create)

class DiaryAPI {
  private rdb: Rdb
  
  constructor() {
    this.rdb = new Rdb(SQL_CREATE_TABLE);
  }
  
  // 🔥 插入单条记录
  async insertRecord(diary: DiaryRecord): Promise<number> {
    try {
      // 确保数据库已初始化
      await this.rdb.getRdbStore();
      
      if (!this.rdb.rdbStore) {
        throw new Error('数据库未初始化');
      }
      
      // 构造ValuesBucket对象
      const valueBucket: relationalStore.ValuesBucket = {
        title: diary.title,
        content: diary.content,
        time: diary.time
      };
      
      // 插入数据
      const rowId = await this.rdb.rdbStore.insert('diary', valueBucket);
      
      console.info(`✅ 日记插入成功,ID: ${rowId}`);
      return rowId;
      
    } catch (error) {
      console.error('❌ 插入日记失败:', error);
      throw error;
    }
  }
  
  // 🔥 批量插入
  async insertBatch(diaries: DiaryRecord[]): Promise<number> {
    if (!this.rdb.rdbStore) {
      throw new Error('数据库未初始化');
    }
    
    try {
      let successCount = 0;
      
      // 使用事务批量插入
      await this.rdb.rdbStore.executeSql('BEGIN TRANSACTION');
      
      for (const diary of diaries) {
        const valueBucket: relationalStore.ValuesBucket = {
          title: diary.title,
          content: diary.content,
          time: diary.time
        };
        
        await this.rdb.rdbStore.insert('diary', valueBucket);
        successCount++;
      }
      
      await this.rdb.rdbStore.executeSql('COMMIT');
      console.info(`✅ 批量插入成功,数量: ${successCount}`);
      
      return successCount;
      
    } catch (error) {
      // 回滚事务
      if (this.rdb.rdbStore) {
        await this.rdb.rdbStore.executeSql('ROLLBACK');
      }
      console.error('❌ 批量插入失败:', error);
      throw error;
    }
  }
}

2. 查询数据(Read)

// 🔥 查询所有记录
async queryAllRecords(): Promise<DiaryRecordSet> {
  await this.rdb.getRdbStore();
  
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    // 查询条件(查询所有,按时间倒序)
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.orderByDesc('time'); // 按时间降序排列
    
    // 执行查询
    const resultSet = await this.rdb.rdbStore.query(predicates);
    
    console.info(`✅ 查询成功,找到${resultSet.rowCount}条记录`);
    
    // 转换结果
    const recordSet = new DiaryRecordSet();
    
    // 遍历结果集
    if (resultSet.goToFirstRow()) {
      do {
        const diary = new DiaryRecord('', '', '');
        diary.id = resultSet.getLong(resultSet.getColumnIndex('id'));
        diary.title = resultSet.getString(resultSet.getColumnIndex('title'));
        diary.content = resultSet.getString(resultSet.getColumnIndex('content'));
        diary.time = resultSet.getString(resultSet.getColumnIndex('time'));
        
        recordSet.addRecord(diary);
      } while (resultSet.goToNextRow());
    }
    
    // 关闭结果集
    resultSet.close();
    
    return recordSet;
    
  } catch (error) {
    console.error('❌ 查询失败:', error);
    throw error;
  }
}

// 🔥 根据ID查询
async queryById(id: number): Promise<DiaryRecord | null> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.equalTo('id', id); // WHERE id = ?
    
    const resultSet = await this.rdb.rdbStore.query(predicates);
    
    let diary: DiaryRecord | null = null;
    
    if (resultSet.goToFirstRow()) {
      diary = new DiaryRecord('', '', '');
      diary.id = resultSet.getLong(resultSet.getColumnIndex('id'));
      diary.title = resultSet.getString(resultSet.getColumnIndex('title'));
      diary.content = resultSet.getString(resultSet.getColumnIndex('content'));
      diary.time = resultSet.getString(resultSet.getColumnIndex('time'));
    }
    
    resultSet.close();
    return diary;
    
  } catch (error) {
    console.error('❌ 根据ID查询失败:', error);
    throw error;
  }
}

// 🔥 模糊搜索
async searchByKeyword(keyword: string): Promise<DiaryRecordSet> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    
    // WHERE title LIKE '%keyword%' OR content LIKE '%keyword%'
    predicates.like('title', `%${keyword}%`)
      .or()
      .like('content', `%${keyword}%`);
    
    predicates.orderByDesc('time');
    
    const resultSet = await this.rdb.rdbStore.query(predicates);
    
    const recordSet = new DiaryRecordSet();
    
    if (resultSet.goToFirstRow()) {
      do {
        const diary = new DiaryRecord('', '', '');
        diary.id = resultSet.getLong(resultSet.getColumnIndex('id'));
        diary.title = resultSet.getString(resultSet.getColumnIndex('title'));
        diary.content = resultSet.getString(resultSet.getColumnIndex('content'));
        diary.time = resultSet.getString(resultSet.getColumnIndex('time'));
        
        recordSet.addRecord(diary);
      } while (resultSet.goToNextRow());
    }
    
    resultSet.close();
    
    console.info(`✅ 搜索完成,找到${recordSet.length}条匹配记录`);
    return recordSet;
    
  } catch (error) {
    console.error('❌ 搜索失败:', error);
    throw error;
  }
}

// 🔥 分页查询
async queryByPage(pageNum: number, pageSize: number): Promise<DiaryRecordSet> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.orderByDesc('time');
    
    // 限制返回结果数量和偏移量
    predicates.limit(pageSize, (pageNum - 1) * pageSize);
    
    const resultSet = await this.rdb.rdbStore.query(predicates);
    
    const recordSet = new DiaryRecordSet();
    
    if (resultSet.goToFirstRow()) {
      do {
        const diary = new DiaryRecord('', '', '');
        diary.id = resultSet.getLong(resultSet.getColumnIndex('id'));
        diary.title = resultSet.getString(resultSet.getColumnIndex('title'));
        diary.content = resultSet.getString(resultSet.getColumnIndex('content'));
        diary.time = resultSet.getString(resultSet.getColumnIndex('time'));
        
        recordSet.addRecord(diary);
      } while (resultSet.goToNextRow());
    }
    
    resultSet.close();
    
    console.info(`✅ 分页查询完成,第${pageNum}页,${recordSet.length}条记录`);
    return recordSet;
    
  } catch (error) {
    console.error('❌ 分页查询失败:', error);
    throw error;
  }
}

3. 更新数据(Update)

// 🔥 更新记录
async updateRecord(diary: DiaryRecord): Promise<number> {
  if (!this.rdb.rdbStore || !diary.id) {
    throw new Error('数据库未初始化或记录ID无效');
  }
  
  try {
    // 构造更新数据
    const valueBucket: relationalStore.ValuesBucket = {
      title: diary.title,
      content: diary.content,
      time: diary.time
    };
    
    // 更新条件
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.equalTo('id', diary.id);
    
    // 执行更新
    const rows = await this.rdb.rdbStore.update(valueBucket, predicates);
    
    console.info(`✅ 更新成功,影响${rows}`);
    return rows;
    
  } catch (error) {
    console.error('❌ 更新失败:', error);
    throw error;
  }
}

// 🔥 批量更新
async updateBatch(updates: Map<number, DiaryRecord>): Promise<number> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    let totalRows = 0;
    
    await this.rdb.rdbStore.executeSql('BEGIN TRANSACTION');
    
    for (const [id, diary] of updates) {
      const valueBucket: relationalStore.ValuesBucket = {
        title: diary.title,
        content: diary.content,
        time: diary.time
      };
      
      const predicates = new relationalStore.RdbPredicates('diary');
      predicates.equalTo('id', id);
      
      const rows = await this.rdb.rdbStore.update(valueBucket, predicates);
      totalRows += rows;
    }
    
    await this.rdb.rdbStore.executeSql('COMMIT');
    console.info(`✅ 批量更新成功,影响${totalRows}`);
    
    return totalRows;
    
  } catch (error) {
    if (this.rdb.rdbStore) {
      await this.rdb.rdbStore.executeSql('ROLLBACK');
    }
    console.error('❌ 批量更新失败:', error);
    throw error;
  }
}

4. 删除数据(Delete)

// 🔥 删除单条记录
async deleteRecord(id: number): Promise<number> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.equalTo('id', id);
    
    const rows = await this.rdb.rdbStore.delete(predicates);
    
    console.info(`✅ 删除成功,影响${rows}`);
    return rows;
    
  } catch (error) {
    console.error('❌ 删除失败:', error);
    throw error;
  }
}

// 🔥 删除所有记录
async deleteAll(): Promise<number> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    const rows = await this.rdb.rdbStore.delete(predicates);
    
    console.info(`✅ 删除所有记录成功,共${rows}`);
    return rows;
    
  } catch (error) {
    console.error('❌ 删除所有记录失败:', error);
    throw error;
  }
}

// 🔥 根据条件删除
async deleteByCondition(startDate: string, endDate: string): Promise<number> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    predicates.between('time', startDate, endDate);
    
    const rows = await this.rdb.rdbStore.delete(predicates);
    
    console.info(`✅ 条件删除成功,影响${rows}`);
    return rows;
    
  } catch (error) {
    console.error('❌ 条件删除失败:', error);
    throw error;
  }
}

📊 高级查询技巧

RdbPredicates谓词详解

RdbPredicates
查询谓词
比较操作
逻辑操作
模糊匹配
范围查询
排序限制
equalTo 等于
notEqualTo 不等于
greaterThan 大于
lessThan 小于
greaterThanOrEqualTo >=
lessThanOrEqualTo <=
and 与
or 或
not 非
beginWrap 开始分组
endWrap 结束分组
like 模糊匹配
glob 通配符
contains 包含
beginsWith 开头
endsWith 结尾
between 范围
in 在列表中
notIn 不在列表中
isNull 为空
isNotNull 不为空
orderBy 排序
limit 限制
offset 偏移
distinct 去重

复杂查询示例

// 🔥 复杂条件查询
async complexQuery(): Promise<DiaryRecordSet> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const predicates = new relationalStore.RdbPredicates('diary');
    
    // (title LIKE '%工作%' OR content LIKE '%工作%') 
    // AND time >= '2024-01-01' 
    // ORDER BY time DESC 
    // LIMIT 10
    
    predicates.beginWrap()
      .like('title', '%工作%')
      .or()
      .like('content', '%工作%')
      .endWrap()
      .and()
      .greaterThanOrEqualTo('time', '2024-01-01')
      .orderByDesc('time')
      .limit(10);
    
    const resultSet = await this.rdb.rdbStore.query(predicates);
    
    // ... 处理结果集 ...
    
    return recordSet;
    
  } catch (error) {
    console.error('❌ 复杂查询失败:', error);
    throw error;
  }
}

// 🔥 统计查询
async getStatistics(): Promise<{total: number, today: number}> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    // 查询总数
    const totalSql = 'SELECT COUNT(*) as total FROM diary';
    const totalResult = await this.rdb.rdbStore.querySql(totalSql);
    
    let total = 0;
    if (totalResult.goToFirstRow()) {
      total = totalResult.getLong(0);
    }
    totalResult.close();
    
    // 查询今天的日记数
    const today = new Date().toISOString().split('T')[0];
    const todaySql = `SELECT COUNT(*) as count FROM diary WHERE time LIKE '${today}%'`;
    const todayResult = await this.rdb.rdbStore.querySql(todaySql);
    
    let todayCount = 0;
    if (todayResult.goToFirstRow()) {
      todayCount = todayResult.getLong(0);
    }
    todayResult.close();
    
    return { total, today: todayCount };
    
  } catch (error) {
    console.error('❌ 统计查询失败:', error);
    throw error;
  }
}

// 🔥 分组查询
async groupByDate(): Promise<Map<string, number>> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    // 按日期分组统计
    const sql = `
      SELECT 
        DATE(time) as date, 
        COUNT(*) as count 
      FROM diary 
      GROUP BY DATE(time) 
      ORDER BY date DESC
    `;
    
    const resultSet = await this.rdb.rdbStore.querySql(sql);
    
    const result = new Map<string, number>();
    
    if (resultSet.goToFirstRow()) {
      do {
        const date = resultSet.getString(0);
        const count = resultSet.getLong(1);
        result.set(date, count);
      } while (resultSet.goToNextRow());
    }
    
    resultSet.close();
    
    console.info(`✅ 分组查询完成,${result.size}个日期`);
    return result;
    
  } catch (error) {
    console.error('❌ 分组查询失败:', error);
    throw error;
  }
}

🔧 性能优化技巧

1. 创建索引

// 创建索引提升查询性能
async createIndexes() {
  if (!this.rdb.rdbStore) {
    return;
  }
  
  try {
    // 时间索引(用于排序和范围查询)
    await this.rdb.rdbStore.executeSql(
      'CREATE INDEX IF NOT EXISTS idx_time ON diary(time DESC)'
    );
    
    // 标题索引(用于搜索)
    await this.rdb.rdbStore.executeSql(
      'CREATE INDEX IF NOT EXISTS idx_title ON diary(title)'
    );
    
    // 全文搜索索引(SQLite FTS5)
    await this.rdb.rdbStore.executeSql(`
      CREATE VIRTUAL TABLE IF NOT EXISTS diary_fts USING fts5(
        title, 
        content, 
        content=diary, 
        content_rowid=id
      )
    `);
    
    console.info('✅ 索引创建成功');
  } catch (error) {
    console.error('❌ 创建索引失败:', error);
  }
}

// 使用全文搜索索引
async fullTextSearch(keyword: string): Promise<DiaryRecordSet> {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    const sql = `
      SELECT diary.* 
      FROM diary 
      JOIN diary_fts ON diary.id = diary_fts.rowid 
      WHERE diary_fts MATCH '${keyword}' 
      ORDER BY diary.time DESC
    `;
    
    const resultSet = await this.rdb.rdbStore.querySql(sql);
    
    // ... 处理结果 ...
    
    return recordSet;
  } catch (error) {
    console.error('❌ 全文搜索失败:', error);
    throw error;
  }
}

2. 使用事务

// 🔥 事务示例
async performTransaction() {
  if (!this.rdb.rdbStore) {
    throw new Error('数据库未初始化');
  }
  
  try {
    // 开始事务
    await this.rdb.rdbStore.executeSql('BEGIN TRANSACTION');
    
    // 执行多个操作
    const diary1 = new DiaryRecord('标题1', '内容1', new Date().toISOString());
    await this.insertRecord(diary1);
    
    const diary2 = new DiaryRecord('标题2', '内容2', new Date().toISOString());
    await this.insertRecord(diary2);
    
    // 提交事务
    await this.rdb.rdbStore.executeSql('COMMIT');
    console.info('✅ 事务提交成功');
    
  } catch (error) {
    // 回滚事务
    if (this.rdb.rdbStore) {
      await this.rdb.rdbStore.executeSql('ROLLBACK');
      console.info('⚠️ 事务已回滚');
    }
    throw error;
  }
}

3. 分页加载

// 🔥 分页加载器
class DiaryPager {
  private pageSize: number = 20
  private currentPage: number = 0
  private hasMore: boolean = true
  
  async loadNextPage(api: DiaryAPI): Promise<DiaryRecord[]> {
    if (!this.hasMore) {
      return [];
    }
    
    this.currentPage++;
    const recordSet = await api.queryByPage(this.currentPage, this.pageSize);
    const records = recordSet.convertToArray();
    
    // 判断是否还有更多数据
    this.hasMore = records.length >= this.pageSize;
    
    console.info(`加载第${this.currentPage}页,${records.length}条记录`);
    return records;
  }
  
  reset() {
    this.currentPage = 0;
    this.hasMore = true;
  }
}

4. 缓存策略

// 🔥 带缓存的数据访问层
class CachedDiaryAPI extends DiaryAPI {
  private cache: Map<number, DiaryRecord> = new Map()
  private cacheTimeout: number = 5 * 60 * 1000 // 5分钟
  private cacheTimestamps: Map<number, number> = new Map()
  
  async queryById(id: number): Promise<DiaryRecord | null> {
    // 检查缓存
    const cached = this.cache.get(id);
    const timestamp = this.cacheTimestamps.get(id);
    
    if (cached && timestamp && Date.now() - timestamp < this.cacheTimeout) {
      console.info(`从缓存获取日记 ID:${id}`);
      return cached;
    }
    
    // 缓存未命中,查询数据库
    const diary = await super.queryById(id);
    
    if (diary) {
      // 更新缓存
      this.cache.set(id, diary);
      this.cacheTimestamps.set(id, Date.now());
    }
    
    return diary;
  }
  
  async updateRecord(diary: DiaryRecord): Promise<number> {
    const rows = await super.updateRecord(diary);
    
    // 更新成功后清除缓存
    if (rows > 0 && diary.id) {
      this.cache.delete(diary.id);
      this.cacheTimestamps.delete(diary.id);
    }
    
    return rows;
  }
  
  clearCache() {
    this.cache.clear();
    this.cacheTimestamps.clear();
    console.info('缓存已清空');
  }
}

🔐 数据安全

1. 数据加密

// 启用数据库加密
private STORE_CONFIG: relationalStore.StoreConfig = {
  name: 'diary.db',
  securityLevel: 1,        // S1级别(最高安全级别)
  encrypt: true,           // 启用加密
  // encryptKey: 'your-key' // 可选:自定义加密密钥
}

2. SQL注入防护

// ❌ 不安全的做法
async unsafeQuery(keyword: string) {
  const sql = `SELECT * FROM diary WHERE title = '${keyword}'`;
  // 如果keyword包含恶意SQL,会造成SQL注入
}

// ✅ 安全的做法
async safeQuery(keyword: string) {
  // 使用参数化查询
  const predicates = new relationalStore.RdbPredicates('diary');
  predicates.equalTo('title', keyword); // 自动转义
  
  return await this.rdb.rdbStore.query(predicates);
}

3. 数据备份

// 🔥 数据库备份
async backupDatabase(backupPath: string): Promise<boolean> {
  try {
    const context = getContext();
    const dbPath = `${context.databaseDir}/diary.db`;
    
    // 复制数据库文件到备份位置
    await fileIo.copyFile(dbPath, backupPath);
    
    console.info(`✅ 数据库备份成功: ${backupPath}`);
    return true;
  } catch (error) {
    console.error('❌ 数据库备份失败:', error);
    return false;
  }
}

// 🔥 数据库恢复
async restoreDatabase(backupPath: string): Promise<boolean> {
  try {
    const context = getContext();
    const dbPath = `${context.databaseDir}/diary.db`;
    
    // 关闭当前数据库
    await this.rdb.closeStore();
    
    // 从备份恢复
    await fileIo.copyFile(backupPath, dbPath);
    
    // 重新打开数据库
    await this.rdb.getRdbStore();
    
    console.info(`✅ 数据库恢复成功`);
    return true;
  } catch (error) {
    console.error('❌ 数据库恢复失败:', error);
    return false;
  }
}

📚 最佳实践

✅ 推荐做法

场景 推荐做法 原因
初始化 应用启动时初始化 避免首次查询慢
查询 使用RdbPredicates 类型安全,防SQL注入
批量操作 使用事务 提升性能,保证一致性
大数据 分页加载 避免内存溢出
频繁查询 添加索引 大幅提升查询速度
结果集 及时关闭 释放资源
敏感数据 启用加密 保护数据安全

❌ 避免做法

  1. ❌ 不关闭ResultSet(内存泄漏)
  2. ❌ 主线程执行耗时查询(ANR)
  3. ❌ 不使用事务的批量操作(性能差)
  4. ❌ 字符串拼接SQL(SQL注入风险)
  5. ❌ 忽略错误处理
  6. ❌ 频繁打开关闭数据库

🎓 总结

RelationalStore为HarmonyOS应用提供了强大的数据持久化能力:

功能完善:支持SQL查询、事务、索引、加密

性能优异:异步API、索引优化、批量操作

易于使用:简洁的API、Promise支持、类型安全

安全可靠:数据加密、SQL注入防护、事务保证

生态友好:与鸿蒙生态深度集成

核心要点

  1. 正确初始化:应用启动时初始化数据库
  2. 合理建模:设计好表结构和索引
  3. 安全查询:使用RdbPredicates而非字符串拼接
  4. 性能优化:事务、索引、分页、缓存
  5. 资源管理:及时关闭ResultSet和数据库连接
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐