harmonyOS next开发 如何创建数据库,保存数据以及数据库如何升级兼容以前的数据?

harmonyOS next开发 如何创建数据库,保存数据以及数据库如何升级兼容以前的数据?

阅读 395
1 个回答

在HarmonyOS Next中,你可以使用关系型数据库(Relational Database, RDB)或对象关系映射数据库(Object Relational Mapping, ORM)来存储和管理应用数据。下面我将详细介绍如何创建数据库、保存数据以及处理数据库升级。
一、创建和使用关系型数据库(RDB)

  1. 初始化数据库
import relationalStore from '@ohos.data.relationalStore';

// 定义数据库配置
const config = {
  name: 'MyApplication.db', // 数据库名称
  securityLevel: relationalStore.SecurityLevel.S1, // 安全级别
  encrypt: false // 是否加密
};

// 定义表结构SQL
const SQL_CREATE_TABLE = `
  CREATE TABLE IF NOT EXISTS user (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    age INTEGER,
    email TEXT
  )
`;

let rdbStore: relationalStore.RdbStore;

async function initDatabase() {
  try {
    // 获取RDB实例
    rdbStore = await relationalStore.getRdbStore(globalThis.context, config);
    
    // 创建表
    await rdbStore.executeSql(SQL_CREATE_TABLE);
    
    console.info('Database initialized successfully');
  } catch (err) {
    console.error(`Failed to initialize database. Code:${err.code}, message:${err.message}`);
  }
}
  1. 插入数据
async function insertUser(user: {name: string, age: number, email: string}) {
  try {
    const valueBucket = {
      'name': user.name,
      'age': user.age,
      'email': user.email
    };
    
    await rdbStore.insert('user', valueBucket);
    console.info('Insert user successfully');
  } catch (err) {
    console.error(`Failed to insert user. Code:${err.code}, message:${err.message}`);
  }
}
  1. 查询数据
async function queryUsers() {
  try {
    const predicates = new relationalStore.RdbPredicates('user');
    // 可以添加查询条件,例如:
    // predicates.equalTo('age', 25);
    
    const resultSet = await rdbStore.query(predicates, ['id', 'name', 'age', 'email']);
    
    const users = [];
    while (resultSet.goToNextRow()) {
      users.push({
        id: resultSet.getLong(resultSet.getColumnIndex('id')),
        name: resultSet.getString(resultSet.getColumnIndex('name')),
        age: resultSet.getLong(resultSet.getColumnIndex('age')),
        email: resultSet.getString(resultSet.getColumnIndex('email'))
      });
    }
    
    resultSet.close();
    return users;
  } catch (err) {
    console.error(`Failed to query users. Code:${err.code}, message:${err.message}`);
    return [];
  }
}

二、数据库升级与数据迁移

  1. 使用版本管理
const config = {
  name: 'MyApplication.db',
  securityLevel: relationalStore.SecurityLevel.S1,
  encrypt: false,
  version: 2 // 初始版本为1,升级后改为2
};
  1. 实现升级回调
const storeConfig = {
  ...config,
  onCreate: (store: relationalStore.RdbStore) => {
    // 初次创建数据库时执行
    store.executeSql(SQL_CREATE_TABLE);
    console.info('Database created');
  },
  onUpgrade: (store: relationalStore.RdbStore, oldVersion: number, newVersion: number) => {
    // 数据库升级时执行
    console.info(`Upgrading database from version ${oldVersion} to ${newVersion}`);
    
    // 根据版本号逐步升级
    for (let version = oldVersion + 1; version <= newVersion; version++) {
      switch (version) {
        case 2:
          // 版本2升级逻辑
          store.executeSql('ALTER TABLE user ADD COLUMN address TEXT');
          break;
        case 3:
          // 版本3升级逻辑
          store.executeSql('CREATE TABLE IF NOT EXISTS settings (key TEXT PRIMARY KEY, value TEXT)');
          break;
        // 可以继续添加更多版本升级逻辑
      }
    }
  }
};

async function initDatabase() {
  try {
    rdbStore = await relationalStore.getRdbStore(globalThis.context, storeConfig);
    console.info('Database initialized successfully');
  } catch (err) {
    console.error(`Failed to initialize database. Code:${err.code}, message:${err.message}`);
  }
}
  1. 复杂数据迁移示例
case 2:
  // 示例:将user表中的name拆分为firstName和lastName
  await store.executeSql('ALTER TABLE user ADD COLUMN firstName TEXT');
  await store.executeSql('ALTER TABLE user ADD COLUMN lastName TEXT');
  
  // 迁移现有数据
  const resultSet = await store.querySql('SELECT id, name FROM user');
  while (resultSet.goToNextRow()) {
    const id = resultSet.getLong(0);
    const fullName = resultSet.getString(1);
    const [firstName, lastName] = fullName.split(' ');
    
    await store.updateSql(
      'UPDATE user SET firstName = ?, lastName = ? WHERE id = ?',
      [firstName, lastName || '', id]
    );
  }
  resultSet.close();
  
  // 可选:删除旧列
  // await store.executeSql('ALTER TABLE user DROP COLUMN name');
  break;

三、使用对象关系映射(ORM)数据库
HarmonyOS也提供了ORM数据库支持,可以更面向对象地操作数据:

  1. 定义实体类
import { Entity, Column, PrimaryColumn } from '@ohos/data.orm';

@Entity('user')
export class User {
  @PrimaryColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  age: number;

  @Column({ name: 'email_address' })
  email: string;
}
  1. 初始化ORM数据库
import { OrmContext, OrmDatabase, DatabaseConfig } from '@ohos/data.orm';

const config: DatabaseConfig = {
  name: 'MyOrmDatabase.db',
  version: 2,
  entities: [User],
  securityLevel: relationalStore.SecurityLevel.S1,
  encrypt: false
};

async function initOrmDatabase() {
  try {
    const ormContext = await OrmContext.getContext(globalThis.context);
    const ormDatabase = await ormContext.getOrmDatabase(config);
    
    // 设置升级处理器
    ormDatabase.onUpgrade((database: OrmDatabase, oldVersion: number, newVersion: number) => {
      // 处理升级逻辑
    });
    
    console.info('ORM database initialized successfully');
    return ormDatabase;
  } catch (err) {
    console.error(`Failed to initialize ORM database. Code:${err.code}, message:${err.message}`);
    throw err;
  }
}
  1. 使用ORM操作数据
async function ormOperations(ormDatabase: OrmDatabase) {
  // 插入数据
  const user = new User();
  user.id = 1;
  user.name = '张三';
  user.age = 30;
  user.email = 'zhangsan@example.com';
  
  await ormDatabase.insert(user);
  
  // 查询数据
  const users = await ormDatabase.query(User)
    .equalTo('age', 30)
    .all();
  
  // 更新数据
  if (users.length > 0) {
    const firstUser = users[0];
    firstUser.age = 31;
    await ormDatabase.update(firstUser);
  }
  
  // 删除数据
  await ormDatabase.delete(user);
}

四、最佳实践
数据库版本管理:

每次数据库结构变更都应增加版本号

在onUpgrade中处理所有版本间的升级路径

数据迁移安全:

在升级前备份重要数据

使用事务确保迁移操作的原子性

性能优化:

对于大批量数据操作,考虑使用事务

合理创建索引提高查询性能

兼容性处理:

新版本应兼容旧版本的数据结构

考虑使用ALTER TABLE而不是删除重建表

错误处理:

捕获并妥善处理所有数据库操作异常

提供适当的用户反馈和恢复机制

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进