HarmonyOS应用开发之数据存储进阶:关系型数据库与分布式数据管理

HarmonyOS数据存储进阶指南

数据存储是移动应用的核心能力之一。在前一篇文章介绍了轻量级偏好数据存储的基础上,本文将深入探讨HarmonyOS中更强大的数据存储方案:关系型数据库和分布式数据管理,帮助您构建数据密集型的高质量应用。

一、关系型数据库深度解析

1.1 关系型数据库基础概念

关系型数据库基于SQLite实现,提供了完整的SQL支持和ACID事务特性,适合存储结构化数据。

核心优势

  • 结构化存储:表结构明确,数据关系清晰
  • 复杂查询:支持SQL语法,可执行多表连接、聚合等复杂操作
  • 事务支持:保证数据操作的原子性和一致性
  • 数据完整性:支持约束、索引等完整性机制

1.2 数据库创建与表管理

import relationalStore from '@ohos.data.relationalStore'

@Component
struct DatabaseExample {
  private rdbStore: relationalStore.RdbStore | null = null
  
  // 数据库配置
  private readonly config: relationalStore.StoreConfig = {
    name: 'user_database.db',
    securityLevel: relationalStore.SecurityLevel.S1
  }

  // 用户表SQL定义
  private readonly USER_TABLE_SQL = `
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      email TEXT UNIQUE,
      age INTEGER,
      created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
      updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
  `

  // 初始化数据库
  async initDatabase() {
    try {
      this.rdbStore = await relationalStore.getRdbStore(this.context, this.config)
      await this.rdbStore.executeSql(this.USER_TABLE_SQL)
      console.log('数据库初始化成功')
    } catch (err) {
      console.error('数据库初始化失败:', err)
    }
  }
}

1.3 数据操作:完整的CRUD实现

插入数据

async addUser(user: Omit<User, 'id'>): Promise<number> {
  if (!this.rdbStore) throw new Error('数据库未初始化')

  const valueBucket: relationalStore.ValuesBucket = {
    'name': user.name,
    'email': user.email,
    'age': user.age,
    'created_time': new Date().toISOString(),
    'updated_time': new Date().toISOString()
  }

  try {
    const insertId = await this.rdbStore.insert('users', valueBucket)
    console.log('用户添加成功,ID:', insertId)
    return insertId
  } catch (err) {
    console.error('添加用户失败:', err)
    throw err
  }
}

查询数据

async getUsers(conditions?: QueryConditions): Promise<User[]> {
  if (!this.rdbStore) return []

  const predicates = new relationalStore.RdbPredicates('users')
  
  // 条件筛选
  if (conditions?.minAge) {
    predicates.greaterThanOrEqualTo('age', conditions.minAge)
  }
  
  if (conditions?.name) {
    predicates.contains('name', conditions.name)
  }

  // 排序
  predicates.orderByAsc(conditions?.sortBy || 'created_time')

  // 分页
  if (conditions?.limit) {
    predicates.limit(conditions.limit)
    predicates.offset(conditions.offset || 0)
  }

  const columns = ['id', 'name', 'email', 'age', 'created_time']
  
  try {
    const resultSet = await this.rdbStore.query(predicates, columns)
    const users: User[] = []
    
    while (resultSet.goToNextRow()) {
      users.push({
        id: resultSet.getLong(resultSet.getColumnIndex('id')),
        name: resultSet.getString(resultSet.getColumnIndex('name')),
        email: resultSet.getString(resultSet.getColumnIndex('email')),
        age: resultSet.getLong(resultSet.getColumnIndex('age')),
        createdTime: resultSet.getString(resultSet.getColumnIndex('created_time'))
      })
    }
    
    resultSet.close()
    return users
  } catch (err) {
    console.error('查询用户失败:', err)
    return []
  }
}

更新数据

async updateUser(userId: number, updates: Partial<User>): Promise<boolean> {
  if (!this.rdbStore) return false

  const valueBucket: relationalStore.ValuesBucket = {
    ...updates,
    'updated_time': new Date().toISOString()
  }

  const predicates = new relationalStore.RdbPredicates('users')
  predicates.equalTo('id', userId)

  try {
    const rowsUpdated = await this.rdbStore.update(valueBucket, predicates)
    return rowsUpdated > 0
  } catch (err) {
    console.error('更新用户失败:', err)
    return false
  }
}

删除数据

async deleteUser(userId: number): Promise<boolean> {
  if (!this.rdbStore) return false

  const predicates = new relationalStore.RdbPredicates('users')
  predicates.equalTo('id', userId)

  try {
    const rowsDeleted = await this.rdbStore.delete(predicates)
    return rowsDeleted > 0
  } catch (err) {
    console.error('删除用户失败:', err)
    return false
  }
}

二、高级数据库特性

2.1 事务处理与数据一致性

事务是保证数据一致性的关键机制,特别是在复杂的业务逻辑中。

async transferPoints(fromUserId: number, toUserId: number, points: number): Promise<boolean> {
  if (!this.rdbStore) return false

  try {
    // 开始事务
    await this.rdbStore.beginTransaction()
    
    // 1. 检查转出用户积分是否足够
    const fromUserPoints = await this.getUserPoints(fromUserId)
    if (fromUserPoints < points) {
      throw new Error('积分不足')
    }
    
    // 2. 扣除转出用户积分
    await this.updateUserPoints(fromUserId, fromUserPoints - points)
    
    // 3. 增加转入用户积分
    const toUserPoints = await this.getUserPoints(toUserId)
    await this.updateUserPoints(toUserId, toUserPoints + points)
    
    // 4. 记录交易日志
    await this.logTransaction(fromUserId, toUserId, points)
    
    // 提交事务
    await this.rdbStore.commit()
    console.log('积分转移成功')
    return true
    
  } catch (err) {
    // 回滚事务
    await this.rdbStore.rollback()
    console.error('积分转移失败:', err)
    return false
  }
}

2.2 数据库索引与性能优化

合理的索引设计可以显著提升查询性能。

// 创建索引的SQL语句
private readonly CREATE_INDEX_SQL = [
  'CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)',
  'CREATE INDEX IF NOT EXISTS idx_users_created_time ON users(created_time)',
  'CREATE INDEX IF NOT EXISTS idx_users_age ON users(age)'
]

// 执行索引创建
async createIndexes() {
  if (!this.rdbStore) return
  
  for (const sql of this.CREATE_INDEX_SQL) {
    try {
      await this.rdbStore.executeSql(sql)
      console.log('索引创建成功:', sql)
    } catch (err) {
      console.error('索引创建失败:', err)
    }
  }
}

2.3 数据库迁移策略

当数据结构发生变化时,需要合理的迁移策略。

class DatabaseMigration {
  private readonly migrations = [
    {
      version: 2,
      sql: 'ALTER TABLE users ADD COLUMN avatar_url TEXT'
    },
    {
      version: 3,
      sql: 'CREATE TABLE IF NOT EXISTS user_settings (user_id INTEGER, theme TEXT)'
    }
  ]

  async migrateDatabase(currentVersion: number, targetVersion: number) {
    const migrationsToRun = this.migrations.filter(m => m.version > currentVersion && m.version <= targetVersion)
    
    for (const migration of migrationsToRun) {
      try {
        await this.rdbStore.executeSql(migration.sql)
        await this.updateSchemaVersion(migration.version)
        console.log(`数据库迁移到版本 ${migration.version} 成功`)
      } catch (err) {
        console.error(`数据库迁移到版本 ${migration.version} 失败:`, err)
        throw err
      }
    }
  }
}

三、分布式数据管理

3.1 分布式数据基础概念

HarmonyOS的分布式数据管理允许应用在多个设备间同步数据,为用户提供无缝的跨设备体验。

核心特性

  • 跨设备数据同步:自动在信任圈设备间同步数据
  • 冲突解决:提供多种冲突解决策略
  • 离线支持:离线操作,联网后自动同步
  • 安全加密:端到端的数据加密传输

3.2 分布式数据库实战

import distributedData from '@ohos.data.distributedData'

@Component
struct DistributedDatabaseExample {
  private kvManager: distributedData.KVManager | null = null
  private kvStore: distributedData.KVStore | null = null
  
  // 初始化分布式数据库
  async initDistributedDB() {
    try {
      // 创建KVManager配置
      const config: distributedData.KVManagerConfig = {
        bundleName: 'com.example.myapp',
        userInfo: {
          userId: 'user123',
          userType: distributedData.UserType.SAME_USER_ID
        }
      }
      
      // 创建KVManager实例
      this.kvManager = distributedData.createKVManager(config)
      
      // 创建KVStore配置
      const options: distributedData.Options = {
        createIfMissing: true,
        encrypt: false,
        backup: false,
        autoSync: true,
        kvStoreType: distributedData.KVStoreType.DEVICE_COLLABORATION,
        securityLevel: distributedData.SecurityLevel.S1
      }
      
      // 创建KVStore实例
      this.kvStore = await this.kvManager.getKVStore('my_distributed_store', options)
      console.log('分布式数据库初始化成功')
      
    } catch (err) {
      console.error('分布式数据库初始化失败:', err)
    }
  }
}

3.3 分布式数据操作

数据存储与同步

// 存储数据到本地并同步到其他设备
async saveUserProfile(user: User): Promise<void> {
  if (!this.kvStore) throw new Error('分布式数据库未初始化')
  
  try {
    // 将对象转换为字符串存储
    const userJson = JSON.stringify(user)
    await this.kvStore.put('user_profile', userJson)
    console.log('用户资料保存成功')
    
    // 手动触发同步(如果autoSync为false)
    await this.kvStore.sync({
      devices: ['all'],
      mode: distributedData.SyncMode.PUSH
    })
    
  } catch (err) {
    console.error('用户资料保存失败:', err)
    throw err
  }
}

// 从分布式数据库读取数据
async getUserProfile(): Promise<User | null> {
  if (!this.kvStore) return null
  
  try {
    const userJson = await this.kvStore.get('user_profile')
    if (userJson) {
      return JSON.parse(userJson.toString())
    }
    return null
  } catch (err) {
    console.error('获取用户资料失败:', err)
    return null
  }
}

数据订阅与实时同步

// 订阅数据变化
async subscribeToDataChanges() {
  if (!this.kvStore) return
  
  try {
    // 订阅特定key的变化
    await this.kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
      console.log('数据发生变化:', data)
      this.handleDataChange(data)
    })
    
    console.log('数据变化订阅成功')
  } catch (err) {
    console.error('数据变化订阅失败:', err)
  }
}

// 处理数据变化
private handleDataChange(changeData: distributedData.ChangeData) {
  const insertedEntries = changeData.insertEntries
  const updatedEntries = changeData.updateEntries
  const deletedEntries = changeData.deleteEntries
  
  // 处理插入的数据
  if (insertedEntries && insertedEntries.length > 0) {
    insertedEntries.forEach(entry => {
      console.log('新增数据:', entry.key, entry.value)
      this.updateUI(entry.key, entry.value)
    })
  }
  
  // 处理更新的数据
  if (updatedEntries && updatedEntries.length > 0) {
    updatedEntries.forEach(entry => {
      console.log('更新数据:', entry.key, entry.value)
      this.updateUI(entry.key, entry.value)
    })
  }
  
  // 处理删除的数据
  if (deletedEntries && deletedEntries.length > 0) {
    deletedEntries.forEach(entry => {
      console.log('删除数据:', entry.key)
      this.removeFromUI(entry.key)
    })
  }
}

四、数据安全与隐私保护

4.1 数据加密策略

// 创建加密的数据库
async createEncryptedDatabase() {
  try {
    const config: relationalStore.StoreConfig = {
      name: 'encrypted_database.db',
      securityLevel: relationalStore.SecurityLevel.S2, // 更高安全级别
      encrypt: true, // 启用加密
      // 在实际应用中,密钥应该从安全存储中获取
      key: this.getEncryptionKey()
    }
    
    this.rdbStore = await relationalStore.getRdbStore(this.context, config)
    console.log('加密数据库创建成功')
  } catch (err) {
    console.error('加密数据库创建失败:', err)
  }
}

// 分布式数据加密
async createEncryptedDistributedDB() {
  const options: distributedData.Options = {
    createIfMissing: true,
    encrypt: true, // 启用加密
    securityLevel: distributedData.SecurityLevel.S2,
    kvStoreType: distributedData.KVStoreType.DEVICE_COLLABORATION
  }
  
  this.kvStore = await this.kvManager.getKVStore('encrypted_store', options)
}

4.2 数据备份与恢复

// 数据库备份
async backupDatabase(): Promise<boolean> {
  if (!this.rdbStore) return false
  
  try {
    const backupPath = this.context.filesDir + '/backup/database_backup.db'
    await this.rdbStore.backup(backupPath)
    console.log('数据库备份成功:', backupPath)
    return true
  } catch (err) {
    console.error('数据库备份失败:', err)
    return false
  }
}

// 数据库恢复
async restoreDatabase(): Promise<boolean> {
  if (!this.rdbStore) return false
  
  try {
    const backupPath = this.context.filesDir + '/backup/database_backup.db'
    await this.rdbStore.restore(backupPath)
    console.log('数据库恢复成功')
    return true
  } catch (err) {
    console.error('数据库恢复失败:', err)
    return false
  }
}

五、实战应用:多设备笔记应用

5.1 数据模型设计

// 笔记数据模型
interface Note {
  id: string
  title: string
  content: string
  category: string
  tags: string[]
  createdTime: string
  updatedTime: string
  deviceId: string // 记录创建设备
  isSynced: boolean // 同步状态
}

// 分类数据模型
interface Category {
  id: string
  name: string
  color: string
  sortOrder: number
}

5.2 混合存储策略实现

结合关系型数据库和分布式数据管理的优势:

class NoteManager {
  private rdbStore: relationalStore.RdbStore | null = null
  private kvStore: distributedData.KVStore | null = null
  
  // 保存笔记(本地存储+分布式同步)
  async saveNote(note: Note): Promise<void> {
    // 1. 保存到本地关系型数据库
    await this.saveToLocalDB(note)
    
    // 2. 同步到分布式数据库
    await this.syncToDistributedDB(note)
    
    // 3. 标记同步状态
    await this.markAsSynced(note.id)
  }
  
  // 从所有设备获取笔记
  async getAllNotes(): Promise<Note[]> {
    const localNotes = await this.getLocalNotes()
    const distributedNotes = await this.getDistributedNotes()
    
    // 合并并去重
    return this.mergeNotes(localNotes, distributedNotes)
  }
  
  // 处理冲突解决
  private mergeNotes(localNotes: Note[], distributedNotes: Note[]): Note[] {
    const noteMap = new Map<string, Note>()
    
    // 优先使用最新更新的笔记
    const allNotes = [...localNotes, ...distributedNotes]
    allNotes.forEach(note => {
      const existing = noteMap.get(note.id)
      if (!existing || new Date(note.updatedTime) > new Date(existing.updatedTime)) {
        noteMap.set(note.id, note)
      }
    })
    
    return Array.from(noteMap.values()).sort((a, b) => 
      new Date(b.updatedTime).getTime() - new Date(a.updatedTime).getTime()
    )
  }
}

5.3 离线优先策略

// 离线优先的数据访问层
class OfflineFirstDataManager {
  async saveNoteOfflineFirst(note: Note): Promise<void> {
    try {
      // 1. 总是先保存到本地
      await this.saveToLocalDB(note)
      
      // 2. 尝试同步到云端(如果在线)
      if (await this.isOnline()) {
        await this.syncToCloud(note)
        await this.markAsSynced(note.id)
      } else {
        // 3. 离线状态:排队等待同步
        await this.queueForSync(note)
      }
    } catch (err) {
      console.error('保存笔记失败:', err)
      throw err
    }
  }
  
  // 定期同步排队的数据
  async syncQueuedNotes(): Promise<void> {
    if (!await this.isOnline()) return
    
    const queuedNotes = await this.getQueuedNotes()
    for (const note of queuedNotes) {
      try {
        await this.syncToCloud(note)
        await this.markAsSynced(note.id)
        await this.removeFromQueue(note.id)
      } catch (err) {
        console.error(`同步笔记 ${note.id} 失败:`, err)
      }
    }
  }
}

六、性能优化与最佳实践

6.1 数据库性能优化

查询优化

// 使用预编译语句提高查询性能
async getUsersWithPreparedQuery(): Promise<User[]> {
  if (!this.rdbStore) return []
  
  const sql = 'SELECT * FROM users WHERE age > ? AND name LIKE ? ORDER BY created_time LIMIT ?'
  const args = [18, '%张%', 100]
  
  try {
    const resultSet = await this.rdbStore.querySql(sql, args)
    // ... 处理结果集
    return users
  } catch (err) {
    console.error('预编译查询失败:', err)
    return []
  }
}

批量操作优化

// 批量插入数据
async batchInsertUsers(users: Omit<User, 'id'>[]): Promise<void> {
  if (!this.rdbStore) return
  
  try {
    await this.rdbStore.beginTransaction()
    
    for (const user of users) {
      const valueBucket: relationalStore.ValuesBucket = {
        'name': user.name,
        'email': user.email,
        'age': user.age,
        'created_time': new Date().toISOString()
      }
      await this.rdbStore.insert('users', valueBucket)
    }
    
    await this.rdbStore.commit()
    console.log(`批量插入 ${users.length} 条数据成功`)
  } catch (err) {
    await this.rdbStore.rollback()
    console.error('批量插入失败:', err)
    throw err
  }
}

6.2 分布式数据优化

同步策略优化

// 智能同步策略
class SmartSyncManager {
  async smartSync(): Promise<void> {
    if (!this.kvStore) return
    
    const syncOptions: distributedData.SyncOptions = {
      devices: ['all'],
      mode: distributedData.SyncMode.PUSH_PULL,
      // 仅在WiFi环境下进行大数据量同步
      allowNetworkTypes: [distributedData.NetworkType.WIFI]
    }
    
    // 根据数据大小选择同步策略
    const dataSize = await this.estimateDataSize()
    if (dataSize > 1024 * 1024) { // 1MB以上
      syncOptions.mode = distributedData.SyncMode.PUSH
      console.log('大数据量,使用PUSH模式')
    }
    
    await this.kvStore.sync(syncOptions)
  }
}

总结

通过本文的深入学习,您应该掌握了HarmonyOS高级数据存储的核心技能:

  1. 关系型数据库:完整的CRUD操作、事务处理和性能优化
  2. 分布式数据管理:跨设备数据同步和冲突解决策略
  3. 数据安全:加密存储和隐私保护机制
  4. 实战应用:多设备笔记应用的完整数据架构
  5. 性能优化:查询优化和智能同步策略

选择合适的数据存储方案需要根据具体业务需求:

  • 简单配置:使用轻量级偏好数据
  • 复杂查询:选择关系型数据库
  • 跨设备同步:采用分布式数据管理
  • 混合需求:结合多种存储方案
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值