数据存储是移动应用的核心能力之一。在前一篇文章介绍了轻量级偏好数据存储的基础上,本文将深入探讨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高级数据存储的核心技能:
- 关系型数据库:完整的CRUD操作、事务处理和性能优化
- 分布式数据管理:跨设备数据同步和冲突解决策略
- 数据安全:加密存储和隐私保护机制
- 实战应用:多设备笔记应用的完整数据架构
- 性能优化:查询优化和智能同步策略
选择合适的数据存储方案需要根据具体业务需求:
- 简单配置:使用轻量级偏好数据
- 复杂查询:选择关系型数据库
- 跨设备同步:采用分布式数据管理
- 混合需求:结合多种存储方案