harmony 鸿蒙关系型数据库开发指导
关系型数据库开发指导
场景介绍
关系型数据库是在SQLite基础上实现的本地数据操作机制,提供给用户无需编写原生SQL语句就能进行数据增删改查的方法,同时也支持原生SQL语句操作。
接口说明
以下是关系型数据库的常用接口说明,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下表均以Promise形式为例,更多接口及使用方式请见关系型数据库。
数据库的创建和删除
关系型数据库提供了数据库创建方式,以及对应的删除接口,涉及的API如下所示。
表1 数据库创建和删除API
| 接口名 | 描述 | 
|---|---|
| getRdbStore(context: Context, config: StoreConfig): Promise<RdbStore> | 获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作,使用Promise异步回调。 -context:应用上下文。 -config:与此RDB存储相关的数据库配置。 | 
| deleteRdbStore(context: Context, name: string): Promise<void> | 使用指定的数据库文件配置删除数据库,使用Promise异步回调。 -context:应用上下文。 -name:数据库名称。 | 
数据库的增删改查
关系型数据库提供对本地数据增删改查操作的能力,相关API如下所示。
- 新增
关系型数据库提供了插入数据的接口,通过ValuesBucket输入要存储的数据,通过返回值判断是否插入成功,插入成功时返回最新插入数据所在的行号,失败时则返回-1。
表2 数据库插入API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | insert(table: string, values: ValuesBucket): Promise<number> | 向目标表中插入一行数据,使用Promise异步回调。 如果操作成功,返回行ID;否则返回-1。 -table:指定的目标表名。 -values:表示要插入到表中的数据行。 | 
- 更新
调用更新接口,传入要更新的数据,并通过RdbPredicates指定更新条件。该接口的返回值表示更新操作影响的行数。如果更新失败,则返回0。
表3 数据库更新API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | update(values: ValuesBucket, predicates: RdbPredicates): Promise<number> | 根据RdbPredicates的指定实例对象更新数据库中的数据,使用Promise异步回调。 返回受影响的行数。 -values:以ValuesBucket存储的要更新的数据。 -predicates:表示RdbPredicates的实例对象指定的更新条件。 | 
- 删除
调用删除接口,通过RdbPredicates指定删除条件。该接口的返回值表示删除的数据行数,可根据此值判断是否删除成功。如果删除失败,则返回0。
表4 数据库删除API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | delete(predicates: RdbPredicates): Promise<number> | 根据RdbPredicates的指定实例对象从数据库中删除数据,使用Promise异步回调。 返回受影响的行数。 -predicates:RdbPredicates的实例对象指定的删除条件。 | 
- 查询
关系型数据库提供了两种查询数据的方式:
- 直接调用查询接口。使用该接口,会将包含查询条件的谓词自动拼接成完整的SQL语句进行查询操作,无需用户传入原生的SQL语句。
- 执行原生的SQL语句进行查询操作。
表5 数据库查询API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | query(predicates: RdbPredicates, columns?: Array<string>): Promise<ResultSet> | 根据指定条件查询数据库中的数据,使用Promise异步回调。 -predicates:表示RdbPredicates的实例对象指定的查询条件。 -columns:表示要查询的列。如果值为空,则查询应用于所有列。 | 
| RdbStore | querySql(sql: string, bindArgs?: Array<ValueType>): Promise<ResultSet> | 根据指定SQL语句查询数据库中的数据,使用Promise异步回调。 -sql:指定要查询的SQL语句。 -bindArgs:SQL语句中参数的值。 | 
| RdbStore | remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array<string>): Promise<ResultSet> | 根据指定条件查询指定远程设备数据库中的数据。使用Promise异步回调。 -device:指定远程查询的设备networkId。 -table:指定远程查询的表名。 -predicates:表示RdbPredicates的实例对象,指定查询的条件。 -columns:表示要查询的列。如果值为空,则查询应用于所有列。 | 
数据库谓词的使用
关系型数据库提供了用于设置数据库操作条件的谓词RdbPredicates,该类确定RDB中条件表达式的值是true还是false。
以下列举几个常用谓词,更多谓词的使用请见关系型数据库谓词。
表6 数据库谓词API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbPredicates | equalTo(field: string, value: ValueType): RdbPredicates | 配置谓词以匹配数据字段为ValueType且值等于指定值的字段。 -field:数据库表中的列名。 -value:指示要与谓词匹配的值。 -RdbPredicates:返回与指定字段匹配的谓词。 | 
| RdbPredicates | notEqualTo(field: string, value: ValueType): RdbPredicates | 配置谓词以匹配数据字段为ValueType且值不等于指定值的字段。 -field:数据库表中的列名。 -value:指示要与谓词匹配的值。 -RdbPredicates:返回与指定字段匹配的谓词。 | 
| RdbPredicates | or(): RdbPredicates | 将或条件添加到谓词中。 -RdbPredicates:返回带有或条件的谓词。 | 
| RdbPredicates | and(): RdbPredicates | 向谓词添加和条件。 -RdbPredicates:返回带有和条件的谓词。 | 
| RdbPredicates | contains(field: string, value: string): RdbPredicates | 配置谓词以匹配数据字段为String且value包含指定值的字段。 -field:数据库表中的列名。 -value:指示要与谓词匹配的值。 -RdbPredicates:返回带有包含条件的谓词。 | 
查询结果集的使用
关系型数据库提供了查询返回的结果集ResultSet,其指向查询结果中的一行数据,供用户对查询结果进行遍历和访问。
更多结果集的接口使用,请见结果集。
须知: 结果集使用完后,请一定要调用close方法显式关闭。
表7 结果集API
| 类名 | 接口名 | 描述 | 
|---|---|---|
| ResultSet | goToFirstRow(): boolean | 将结果集移动到第一行。 | 
| ResultSet | getString(columnIndex: number): string | 获取当前行指定列的值,以String类型返回。 | 
| ResultSet | getBlob(columnIndex: number): Uint8Array | 获取当前行指定列的值,以字节数组形式返回。 | 
| ResultSet | getDouble(columnIndex: number): number | 获取当前行指定列的值,以double型返回。 | 
| ResultSet | getLong(columnIndex: number): number | 获取当前行指定列的值,以Long形式返回。 | 
| ResultSet | close(): void | 关闭结果集。 | 
设置分布式列表
说明:
- 在使用RdbStore的setDistributedTables、obtainDistributedTableName、sync、on、off接口时,需要请求相应的权限:ohos.permission.DISTRIBUTED_DATASYNC。
- 使用分布式列表前,需要先建立设备间组网,具体接口及使用可见设备管理。
设置分布式列表
表8 设置分布式列表
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | setDistributedTables(tables: Array<string>): Promise<void> | 设置分布式列表,使用Promise异步回调。 -tables:要设置的分布式列表表名。 | 
根据本地表名获取指定远程设备的分布式表名
用户根据本地表名获取指定远程设备的分布式表名。在查询远程设备数据库时,需要使用分布式表名。
表9 根据本地表名获取指定远程设备的分布式表名
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | obtainDistributedTableName(device: string, table: string): Promise<string> | 根据本地表名获取指定远程设备的分布式表名。在查询远程设备数据库时,需要使用分布式表名,使用Promise异步回调。 -device:远程设备。 -table:本地表名。 | 
在设备之间同步数据
表10 在设备之间同步数据
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | sync(mode: SyncMode, predicates: RdbPredicates): Promise<Array<[string, number]>> | 在设备之间同步数据,使用Promise异步回调。 -mode:指同步模式。SYNC_MODE_PUSH 表示数据从本地设备推送到远程设备;SYNC_MODE_PULL 表示数据从远程设备拉至本地设备。 -predicates:约束同步数据和设备。 -string:设备ID;number:每个设备同步状态,0表示成功,其他值表示失败。 | 
注册数据库的观察者
表11 注册数据库的观察者
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | on(event: ‘dataChange’, type: SubscribeType, observer: Callback<Array<string>>): void | 注册数据库的观察者。当分布式数据库中的数据发生更改时,将调用回调。 -type:订阅类型;SUBSCRIBE_TYPE_REMOTE 订阅远程数据更改。 -observer:指分布式数据库中数据更改事件的观察者。 | 
从数据库中删除指定类型的指定观察者
表12 从数据库中删除指定类型的指定观察者
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | off(event:‘dataChange’, type: SubscribeType, observer: Callback<Array<string>>): void; | 从数据库中删除指定类型的指定观察者,使用callback异步回调。 -type:订阅类型;SUBSCRIBE_TYPE_REMOTE 订阅远程数据更改。 -observer:指已注册的数据更改观察者。 | 
数据库的备份和恢复
备份
表13 备份数据库
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | backup(destName: string): Promise<void> | 以指定名称备份数据库,使用Promise异步回调。 -destName:指定数据库的备份文件名。 | 
恢复
表14 恢复数据库
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | restore(srcName: string): Promise<void> | 从指定的数据库备份文件恢复数据库,使用Promise异步回调。 -srcName:指定数据库的备份文件名。 | 
事务
表15 事务
| 类名 | 接口名 | 描述 | 
|---|---|---|
| RdbStore | beginTransaction(): void | 在开始执行SQL语句之前,开始事务。 | 
| RdbStore | commit(): void | 提交已执行的SQL语句。 | 
| RdbStore | rollBack(): void | 回滚已经执行的SQL语句。 | 
开发步骤
- 创建数据库。
(1) 配置数据库相关信息,包括数据库的名称、存储模式、是否为只读模式等。
(2) 初始化数据库表结构和相关数据。
(3) 创建数据库。
FA模型示例:
```js
import relationalStore from ‘@ohos.data.relationalStore’ import featureAbility from ‘@ohos.ability.featureAbility’
var store;
// 获取context let context = featureAbility.getContext();
const STORE_CONFIG = { name: “RdbTest.db”, securityLevel: relationalStore.SecurityLevel.S1 };
// 假设当前数据库版本为3 relationalStore.getRdbStore(context, STORE_CONFIG, function (err, rdbStore) { store = rdbStore; // 当数据库创建时,数据库默认版本为0 if (store.version == 0) { store.executeSql(“CREATE TABLE IF NOT EXISTS student (id INTEGER PRIMARY KEY AUTOINCREMENT, score REAL);”, null); // 设置数据库的版本,入参为大于0的整数 store.version = 3; }
 // 当数据库存在并假定版本为1时,例应用从某一版本升级到当前版本,数据库需要从1版本升级到2版本
 if (store.version != 3 && store.version == 1) {
   // version = 1:表结构:student (id, age) => version = 2:表结构:student (id, age, score)
   store.executeSql("ALTER TABLE student ADD COLUMN score REAL", null);
   store.version = 2;
 }
 // 当数据库存在并假定版本为2时,例应用从某一版本升级到当前版本,数据库需要从2版本升级到3版本
 if (store.version != 3 && store.version == 2) {
   // version = 2:表结构:student (id, age, score) => version = 3:表结构:student (id, score)
   store.executeSql("ALTER TABLE student DROP COLUMN age INTEGER", null);
   store.version = 3;
 }
})
    
    Stage模型示例:
ts
   import relationalStore from ‘@ohos.data.relationalStore’
   import UIAbility from ‘@ohos.app.ability.UIAbility’
class EntryAbility extends UIAbility {
       onWindowStageCreate(windowStage) {
         var store;
         const STORE_CONFIG = {
           name: “RdbTest.db”,
           securityLevel: relationalStore.SecurityLevel.S1
         };
     // 假设当前数据库版本为3
     relationalStore.getRdbStore(this.context, STORE_CONFIG, function (err, rdbStore) {
       store = rdbStore;
       // 当数据库创建时,数据库默认版本为0
       if (store.version == 0) {
         store.executeSql("CREATE TABLE IF NOT EXISTS student (id INTEGER PRIMARY KEY AUTOINCREMENT, score REAL);", null);
         // 设置数据库的版本,入参为大于0的整数
         store.version = 3;
       }
       // 当数据库存在并假定版本为1时,例应用从某一版本升级到当前版本,数据库需要从1版本升级到2版本
       if (store.version != 3 && store.version == 1) {
         // version = 1:表结构:student (id, age) => version = 2:表结构:student (id, age, score)
         store.executeSql("ALTER TABLE student ADD COLUMN score REAL", null);
         store.version = 2;
       }
       // 当数据库存在并假定版本为2时,例应用从某一版本升级到当前版本,数据库需要从2版本升级到3版本
       if (store.version != 3 && store.version == 2) {
         // version = 2:表结构:student (id, age, score) => version = 3:表结构:student (id, score)
         store.executeSql("ALTER TABLE student DROP COLUMN age INTEGER", null);
         store.version = 3;
       }
     })
   }
} “`
- 插入数据。
(1) 构造要插入的数据,以ValuesBucket形式存储。
(2) 调用关系型数据库提供的插入接口。
示例代码如下:
```js
let u8 = new Uint8Array([1, 2, 3]);
const valueBucket = { "name": "Tom", "age": 18, "salary": 100.5, "blobType": u8 };
let insertPromise = store.insert("test", valueBucket);
```
```js
//使用事务插入数据
try {
  store.beginTransaction();
  let u8 = new Uint8Array([1, 2, 3]);
  const valueBucket = { "name": "Tom", "age": 18, "salary": 100.5, "blobType": u8 };
  let promise = store.insert("test", valueBucket);
  promise.then(() => {
    store.commit();
  })
} catch (err) {
  console.error(`Transaction failed, err: ${err}`);
  store.rollBack();
}
```
- 查询数据。
(1) 构造用于查询的谓词对象,设置查询条件。
(2) 调用查询接口查询数据。
(3) 调用结果集接口,返回查询结果。
示例代码如下:
```js
let predicates = new relationalStore.RdbPredicates("test");
predicates.equalTo("name", "Tom");
let promisequery = store.query(predicates);
promisequery.then((resultSet) => {
  resultSet.goToFirstRow();
  const id = resultSet.getLong(resultSet.getColumnIndex("id"));
  const name = resultSet.getString(resultSet.getColumnIndex("name"));
  const age = resultSet.getLong(resultSet.getColumnIndex("age"));
  const salary = resultSet.getDouble(resultSet.getColumnIndex("salary"));
  const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType"));
  resultSet.close();
})
```
- 设置分布式同步表。 - (1) 权限配置文件中增加以下配置。 - "requestPermissions": { "name": "ohos.permission.DISTRIBUTED_DATASYNC" }- (2) 获取应用权限。 - (3) 数据库调用接口设置分布式同步列表。 - (4) 判断是否设置成功。 
示例代码如下:
```js
let context = featureAbility.getContext();
context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666, function (result) {
  console.info(`result.requestCode=${result.requestCode}`);
})
let promise = store.setDistributedTables(["test"]);
promise.then(() => {
  console.info(`setDistributedTables success.`);
}).catch((err) => {
  console.error(`setDistributedTables failed, ${err}`);
})
```
- 分布式数据同步。 - (1) 构造用于同步分布式表的谓词对象,指定组网内的远程设备。 - (2) 调用同步数据的接口。 - (3) 判断数据同步是否成功。 - 示例代码如下: - let predicate = new relationalStore.RdbPredicates('test'); predicate.inDevices(['12345678abcde']); let promise = store.sync(relationalStore.SyncMode.SYNC_MODE_PUSH, predicate); promise.then((result) => { console.info(`sync done.`); for (let i = 0; i < result.length; i++) { console.info(`device=${result[i][0]}, status=${result[i][1]}`); } }).catch((err) => { console.error(`sync failed, err: ${err}`); })
- 分布式数据订阅。 - (1) 调用分布式数据订阅接口,注册数据库的观察者。 - (2) 当分布式数据库中的数据发生更改时,将调用回调。 - 示例代码如下: - function storeObserver(devices) { for (let i = 0; i < devices.length; i++) { console.info(`device= ${devices[i]} data changed`); } } try { store.on('dataChange', relationalStore.SubscribeType.SUBSCRIBE_TYPE_REMOTE, storeObserver); } catch (err) { console.error(`register observer failed, err: ${err}`); }
- 跨设备查询。 - (1) 根据本地表名获取指定远程设备的分布式表名。 - (2) 调用结果集接口,返回查询结果。 - 示例代码如下: - ”`js import deviceManager from ‘@ohos.distributedHardware.deviceManager’ 
let deviceIds = []; deviceManager.createDeviceManager(‘bundleName’, (err, value) => { if (!err) { let devManager = value; if (devManager != null) { // 获取deviceIds let devices = devManager.getTrustedDeviceListSync(); for (let i = 0; i < devices.length; i++) { deviceIds[i] = devices[i].deviceId; } } } })
let tableName = store.obtainDistributedTableName(deviceIds[0], “test”); let resultSet = store.querySql(“SELECT * FROM ” + tableName); “`
- 远程查询。
(1) 构造用于查询分布式表的谓词对象,指定组网内的远程分布式表名和设备。
(2) 调用结果集接口,返回查询结果。
示例代码如下:
    let rdbPredicate = new relationalStore.RdbPredicates('employee');
    predicates.greaterThan("id", 0) ;
    let promiseQuery = store.remoteQuery('12345678abcde', 'employee', rdbPredicate);
    promiseQuery.then((resultSet) => {
      while (resultSet.goToNextRow()) {
        let idx = resultSet.getLong(0);
        let name = resultSet.getString(1);
        let age = resultSet.getLong(2);
        console.info(`indx: ${idx}, name: ${name}, age: ${age}`);
      }
      resultSet.close();
    }).catch((err) => {
      console.error(`failed to remoteQuery, err: ${err}`);
    })
- 数据库的备份和恢复。
(1) 调用数据库的备份接口,备份当前数据库文件。
示例代码如下:
    let promiseBackup = store.backup("dbBackup.db");
    promiseBackup.then(() => {
      console.info(`Backup success.`);
    }).catch((err) => {
      console.error(`Backup failed, err: ${err}`);
    })
(2) 调用数据库的恢复接口,从数据库的备份文件恢复数据库文件。
示例代码如下:
    let promiseRestore = store.restore("dbBackup.db");
    promiseRestore.then(() => {
      console.info(`Restore success.`);
    }).catch((err) => {
      console.error(`Restore failed, err: ${err}`);
    })
相关实例
针对关系型数据库开发,有以下相关实例可供参考:
你可能感兴趣的鸿蒙文章
热门推荐
- 
                        2、 - 优质文章
- 
                        3、 gate.io
- 
                        8、 openharmony
- 
                        9、 golang